diff --git a/loader_example.cc b/loader_example.cc index 72fbfd5..599f6ce 100644 --- a/loader_example.cc +++ b/loader_example.cc @@ -361,7 +361,7 @@ static bool TestStreamLoadObj() { virtual ~MaterialStringStreamReader() {} virtual bool operator()(const std::string& matId, std::vector* materials, - std::map* matMap, + std::map* matMap, std::string* err) { (void)matId; std::string warning; diff --git a/tests/tester.cc b/tests/tester.cc index cd972f8..f8cc13e 100644 --- a/tests/tester.cc +++ b/tests/tester.cc @@ -22,22 +22,22 @@ static void PrintInfo(const tinyobj::attrib_t &attrib, const std::vector(attrib.vertices[3*v+0]), - static_cast(attrib.vertices[3*v+1]), - static_cast(attrib.vertices[3*v+2])); + static_cast(attrib.vertices[v].x), + static_cast(attrib.vertices[v].y), + static_cast(attrib.vertices[v].z)); } for (size_t v = 0; v < attrib.normals.size() / 3; v++) { printf(" n[%ld] = (%f, %f, %f)\n", v, - static_cast(attrib.normals[3*v+0]), - static_cast(attrib.normals[3*v+1]), - static_cast(attrib.normals[3*v+2])); + static_cast(attrib.normals[v].x), + static_cast(attrib.normals[v].y), + static_cast(attrib.normals[v].z)); } for (size_t v = 0; v < attrib.texcoords.size() / 2; v++) { printf(" uv[%ld] = (%f, %f)\n", v, - static_cast(attrib.texcoords[2*v+0]), - static_cast(attrib.texcoords[2*v+1])); + static_cast(attrib.texcoords[v].x), + static_cast(attrib.texcoords[v].y)); } for (size_t i = 0; i < shapes.size(); i++) { @@ -303,7 +303,8 @@ std::string matStream( virtual bool operator() ( const std::string& matId, std::vector* materials, - std::map* matMap, + //std::map* matMap, + std::map* matMap, std::string* err) { (void)matId; diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index f519d00..8591252 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -23,6 +23,7 @@ THE SOFTWARE. */ // +// version 2.1.0 : Used new hashed keywords // version 2.0.0 : New API! And support triangulation of concave polygon(#151). // version 1.1.0 : Support parsing vertex color(#144) // version 1.0.8 : Fix parsing `g` tag just after `usemtl`(#138) @@ -285,7 +286,8 @@ class MaterialReader { virtual bool operator()(const std::string &matId, std::vector *materials, - std::map *matMap, + // std::map *matMap, + std::map *matMap, std::string *err) = 0; }; @@ -296,7 +298,9 @@ class MaterialFileReader : public MaterialReader { virtual ~MaterialFileReader() {} virtual bool operator()(const std::string &matId, std::vector *materials, - std::map *matMap, std::string *err); + // std::map *matMap, + std::map *matMap, + std::string *err); private: std::string m_mtlBaseDir; @@ -309,7 +313,9 @@ class MaterialStreamReader : public MaterialReader { virtual ~MaterialStreamReader() {} virtual bool operator()(const std::string &matId, std::vector *materials, - std::map *matMap, std::string *err); + // std::map *matMap, + std::map *matMap, + std::string *err); private: std::istream &m_inStream; @@ -351,9 +357,11 @@ bool LoadObj(attrib_t *attrib, std::vector *shapes, bool triangulate = true); /// Loads materials into std::map -void LoadMtl(std::map *material_map, - std::vector *materials, std::istream *inStream, - std::string *warning); +void LoadMtl( + // std::map *material_map, + std::map *material_map, + std::vector *materials, std::istream *inStream, + std::string *warning); } // namespace tinyobj @@ -371,8 +379,278 @@ void LoadMtl(std::map *material_map, #include #include +//#define TINYOBJLOADER_IMPLEMENTATION_BUFREAD + +#ifdef TINYOBJLOADER_IMPLEMENTATION_BUFREAD +#include +#include +#include +#include + +#define O_LARGEFILE 0100000 +#endif + namespace tinyobj { +#ifdef TINYOBJLOADER_IMPLEMENTATION_BUFREAD +// tigra: ImportInBuf - buffered input file +class ImportInBuf : public std::streambuf { + public: + ImportInBuf(const char *filename, size_t buf_sz_ = 64 * 1024) + : fd_(open(filename, O_RDONLY | O_LARGEFILE)) { + // fprintf(stderr, "ImportInBuf(%s\n", filename); + + if (fd_ < 0) { + fprintf(stderr, "can't open file %s\n", filename); + exit(1); + } + + buf_sz = buf_sz_; + + // fprintf(stderr, "buf_sz=%d\n", buf_sz); + + buffer_ = (char *)malloc(buf_sz); + + setg(buffer_, buffer_, buffer_); + struct stat st; + fstat(fd_, &st); + fsize_ = st.st_size; + + // fprintf(stderr, "file size: %ld\n", fsize_); + } + + // you don't have to do it like this if your streams are 64 bit + void seekg(uint64_t pos) { + lseek(fd_, pos, SEEK_SET); + pos_ = pos; + setg(buffer_, buffer_, buffer_); + } + + uint64_t tellg() const { return pos_; } + uint64_t size() const { return fsize_; } + + ~ImportInBuf() { + close(fd_); + free(buffer_); + } + + private: + ImportInBuf(const ImportInBuf &); + ImportInBuf &operator=(const ImportInBuf &); + virtual int underflow() { + if (gptr() < egptr()) { + return *gptr(); + } + int size = read(fd_, buffer_, buf_sz); + if (size) { + pos_ += size; + setg(buffer_, buffer_, buffer_ + size); + return *gptr(); + } + pos_ = fsize_; + return EOF; + } + + char *buffer_; + int fd_; + uint64_t fsize_, pos_; + size_t buf_sz; +}; +#endif + +//*************************************************** +//*************** tigro keywords hash functions begin + +// tigra: x31 hash function + +typedef unsigned int khint_t; + +inline unsigned int X31_hash_string(const char *s) { + khint_t h = static_cast(*s); + for (++s; *s; ++s) h = (h << 5) - h + static_cast(*s); + return h; +} + +inline unsigned int X31_hash_stringSZ(const char *s, int sz) { + int i; + khint_t h = static_cast(*s); + + for (++s, i = sz - 1; i && *s; ++s, i--) + h = (h << 5) - h + static_cast(*s); + return h; +} + +// tigra: refactoring2 - add list of keywords +static const char *keywords[] = { + // on off + "on", "off", + + // TextureType + "cube_top", "cube_bottom", "cube_left", "cube_right", "cube_front", + "cube_back", "sphere", + + // TextureNameAndOption + "-blendu", "-blendv", "-clamp", "-boost", "-bm", "-o", "-s", "-t", "-type", + "-imfchan", "-mm", + + // newmtl, illum, mtllib, usemtl + "newmtl", "illum", "mtllib", "usemtl", + + // PBR params + "Pcr", "aniso", "anisor", + + // maps + "map_Ka", "map_Kd", "map_Ks", "map_Ns", "map_bump", "map_Bump", "bump", + + // alpha texture + "map_d", + + // displacement texture + "disp", + + // reflection map + "refl", + + // PBR: roughness texture, metallic texture + "map_Pr", "map_Pm", + + // PBR: sheen texture + "map_Ps", + + // PBR: emissive texture + "map_Ke", + + // PBR: normal map texture + "norm"}; + +// tigra: enum of tokens +enum tokens_enum { + // on off + TOK_on, + TOK_off, + + // TextureType + TOK_cube_top, + TOK_cube_bottom, + TOK_cube_left, + TOK_cube_right, + TOK_cube_front, + TOK_cube_back, + TOK_sphere, + + // TextureNameAndOption + TOK_blendu, + TOK_blendv, + TOK_clamp, + TOK_boost, + TOK_bm, + TOK_o, + TOK_s, + TOK_t, + TOK_type, + TOK_imfchan, + TOK_mm, + + // newmtl, illum, mtllib, usemtl + TOK_newmtl, + TOK_illum, + TOK_mtllib, + TOK_usemtl, + + // PBR params + TOK_Pcr, + TOK_aniso, + TOK_anisor, + + // maps + TOK_map_Ka, + TOK_map_Kd, + TOK_map_Ks, + TOK_map_Ns, + TOK_map_bump, + TOK_map_Bump, + TOK_bump, + + // alpha texture + TOK_map_d, + + // displacement texture + TOK_disp, + + // reflection map + TOK_refl, + + // PBR: roughness texture, metallic texture + TOK_map_Pr, + TOK_map_Pm, + + // PBR: sheen texture + TOK_map_Ps, + + // PBR: emissive texture + TOK_map_Ke, + + // PBR: normal map texture + TOK_norm +}; + +// TODO(syoyo): Do not define in global scope. + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wglobal-constructors" +#pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif + +static std::map hashed_toks; + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// functions! +static void initHashedTokensMap() { + // init hashed tokens map + + unsigned int hhh; + int iii; + + if (hashed_toks.empty()) { + for (iii = sizeof(keywords) / sizeof(char *); iii; iii--) { + hhh = X31_hash_string(keywords[iii - 1]); + hashed_toks[hhh] = iii - 1; + } + } + // init hashed tokens map END +} + +// search token in keywords hash map +static int token2tok(const char *token) { + unsigned int token_sz, a_hash; + + int a_tok; + + token_sz = static_cast(strpbrk(token, " \t\r") - + token); // token length + + if (token_sz < 1) // delimiter not found, token_sz = strlen(token) + { + // token_sz=strlen(token); + a_hash = X31_hash_string(token); + } else { + a_hash = X31_hash_stringSZ(token, static_cast(token_sz)); + } + + a_tok = -1; + if (hashed_toks.find(a_hash) != hashed_toks.end()) + a_tok = hashed_toks[a_hash]; + + return a_tok; +} + +//*************** tigro keywords hash functions END +//************************************************* + MaterialReader::~MaterialReader() {} struct vertex_index { @@ -670,11 +948,12 @@ static inline void parseV(real_t *x, real_t *y, real_t *z, real_t *w, } // Extension: parse vertex with colors(6 items) -static inline bool parseVertexWithColor(real_t *x, real_t *y, real_t *z, real_t *r, - real_t *g, real_t *b, - const char **token, const double default_x = 0.0, - const double default_y = 0.0, - const double default_z = 0.0) { +static inline bool parseVertexWithColor(real_t *x, real_t *y, real_t *z, + real_t *r, real_t *g, real_t *b, + const char **token, + const double default_x = 0.0, + const double default_y = 0.0, + const double default_z = 0.0) { (*x) = parseReal(token, default_x); (*y) = parseReal(token, default_y); (*z) = parseReal(token, default_z); @@ -705,22 +984,46 @@ static inline texture_type_t parseTextureType( const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) { (*token) += strspn((*token), " \t"); const char *end = (*token) + strcspn((*token), " \t\r"); + texture_type_t ty = default_value; - if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) { - ty = TEXTURE_TYPE_CUBE_TOP; - } else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) { - ty = TEXTURE_TYPE_CUBE_BOTTOM; - } else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) { - ty = TEXTURE_TYPE_CUBE_LEFT; - } else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) { - ty = TEXTURE_TYPE_CUBE_RIGHT; - } else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) { - ty = TEXTURE_TYPE_CUBE_FRONT; - } else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) { - ty = TEXTURE_TYPE_CUBE_BACK; - } else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) { - ty = TEXTURE_TYPE_SPHERE; + int a_tok; + + // init hashed tokens map + initHashedTokensMap(); + + a_tok = token2tok(*token); + + // tigra: dont check if wrong token + if (a_tok >= TOK_cube_top && a_tok <= TOK_sphere) { + // if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) + if (a_tok == TOK_cube_top) { + ty = TEXTURE_TYPE_CUBE_TOP; + } else + // if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) + if (a_tok == TOK_cube_bottom) { + ty = TEXTURE_TYPE_CUBE_BOTTOM; + } else + // if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) + if (a_tok == TOK_cube_left) { + ty = TEXTURE_TYPE_CUBE_LEFT; + } else + // if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) + if (a_tok == TOK_cube_right) { + ty = TEXTURE_TYPE_CUBE_RIGHT; + } else + // if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) + if (a_tok == TOK_cube_front) { + ty = TEXTURE_TYPE_CUBE_FRONT; + } else + // if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) + if (a_tok == TOK_cube_back) { + ty = TEXTURE_TYPE_CUBE_BACK; + } else + // if ((0 == strncmp((*token), "sphere", strlen("sphere")))) + if (a_tok == TOK_sphere) { + ty = TEXTURE_TYPE_SPHERE; + } } (*token) = end; @@ -737,7 +1040,7 @@ static tag_sizes parseTagTriple(const char **token) { return ts; } - (*token)++; // Skip '/' + (*token)++; // Skip '/' (*token) += strspn((*token), " \t"); ts.num_reals = atoi((*token)); @@ -745,7 +1048,7 @@ static tag_sizes parseTagTriple(const char **token) { if ((*token)[0] != '/') { return ts; } - (*token)++; // Skip '/' + (*token)++; // Skip '/' ts.num_strings = parseInt(token); @@ -872,51 +1175,85 @@ static bool ParseTextureNameAndOption(std::string *texname, const char *token = linebuf; // Assume line ends with NULL + int a_tok; + + // init hashed tokens map + initHashedTokensMap(); + while (!IS_NEW_LINE((*token))) { token += strspn(token, " \t"); // skip space - if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) { - token += 8; - texopt->blendu = parseOnOff(&token, /* default */ true); - } else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) { - token += 8; - texopt->blendv = parseOnOff(&token, /* default */ true); - } else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) { - token += 7; - texopt->clamp = parseOnOff(&token, /* default */ true); - } else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) { - token += 7; - texopt->sharpness = parseReal(&token, 1.0); - } else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) { - token += 4; - texopt->bump_multiplier = parseReal(&token, 1.0); - } else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) { - token += 3; - parseReal3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), - &(texopt->origin_offset[2]), &token); - } else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) { - token += 3; - parseReal3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]), - &token, 1.0, 1.0, 1.0); - } else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) { - token += 3; - parseReal3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), - &(texopt->turbulence[2]), &token); - } else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) { - token += 5; - texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); - } else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) { - token += 9; - token += strspn(token, " \t"); - const char *end = token + strcspn(token, " \t\r"); - if ((end - token) == 1) { // Assume one char for -imfchan - texopt->imfchan = (*token); + + a_tok = token2tok(token); + + // tigra: minimize checks + if (a_tok >= TOK_blendu && a_tok <= TOK_mm) { + // if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) + if (a_tok == TOK_blendu) { + token += 8; + texopt->blendu = parseOnOff(&token, /* default */ true); + } else + // if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) + if (a_tok == TOK_blendv) { + token += 8; + texopt->blendv = parseOnOff(&token, /* default */ true); + } else + // if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) + if (a_tok == TOK_clamp) { + token += 7; + texopt->clamp = parseOnOff(&token, /* default */ true); + } else + // if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) + if (a_tok == TOK_boost) { + token += 7; + texopt->sharpness = parseReal(&token, 1.0); + } else + // if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) + if (a_tok == TOK_bm) { + token += 4; + texopt->bump_multiplier = parseReal(&token, 1.0); + } else + // if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) + if (a_tok == TOK_o) { + token += 3; + parseReal3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]), + &(texopt->origin_offset[2]), &token); + } else + // if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) + if (a_tok == TOK_s) { + token += 3; + parseReal3(&(texopt->scale[0]), &(texopt->scale[1]), + &(texopt->scale[2]), &token, 1.0, 1.0, 1.0); + } else + // if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) + if (a_tok == TOK_t) { + token += 3; + parseReal3(&(texopt->turbulence[0]), &(texopt->turbulence[1]), + &(texopt->turbulence[2]), &token); + } else + // if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) + if (a_tok == TOK_type) { + token += 5; + texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE); + } else + // if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) + if (a_tok == TOK_imfchan) { + token += 9; + token += strspn(token, " \t"); + const char *end = token + strcspn(token, " \t\r"); + if ((end - token) == 1) { // Assume one char for -imfchan + texopt->imfchan = (*token); + } + token = end; + } else + // if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) + if (a_tok == TOK_mm) { + token += 4; + parseReal2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, + 1.0); } - token = end; - } else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) { - token += 4; - parseReal2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0); + } else { - // Assume texture filename +// Assume texture filename #if 0 size_t len = strcspn(token, " \t\r"); // untile next space texture_name = std::string(token, token + len); @@ -1150,9 +1487,11 @@ static void SplitString(const std::string &s, char delim, } } -void LoadMtl(std::map *material_map, - std::vector *materials, std::istream *inStream, - std::string *warning) { +void LoadMtl( + // std::map *material_map, + std::map *material_map, + std::vector *materials, std::istream *inStream, + std::string *warning) { // Create a default material anyway. material_t material; InitMaterial(&material); @@ -1161,6 +1500,11 @@ void LoadMtl(std::map *material_map, bool has_d = false; bool has_tr = false; + int a_tok; + + // init hashed tokens map + initHashedTokensMap(); + std::stringstream ss; std::string linebuf; @@ -1196,106 +1540,136 @@ void LoadMtl(std::map *material_map, if (token[0] == '#') continue; // comment line - // new mtl - if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { - // flush previous material. - if (!material.name.empty()) { - material_map->insert(std::pair( - material.name, static_cast(materials->size()))); - materials->push_back(material); + // group size==2 + if (IS_SPACE((token[2]))) { + // group K + if (token[0] == 'K') { + // ambient + if (token[1] == 'a') { + token += 2; + real_t r, g, b; + parseReal3(&r, &g, &b, &token); + material.ambient[0] = r; + material.ambient[1] = g; + material.ambient[2] = b; + continue; + } + + // diffuse + if (token[1] == 'd') { + token += 2; + real_t r, g, b; + parseReal3(&r, &g, &b, &token); + material.diffuse[0] = r; + material.diffuse[1] = g; + material.diffuse[2] = b; + continue; + } + + // specular + if (token[1] == 's') { + token += 2; + real_t r, g, b; + parseReal3(&r, &g, &b, &token); + material.specular[0] = r; + material.specular[1] = g; + material.specular[2] = b; + continue; + } + + // transmittance + if (token[1] == 't') { + token += 2; + real_t r, g, b; + parseReal3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; + } + + // emission + if (token[1] == 'e') { + token += 2; + real_t r, g, b; + parseReal3(&r, &g, &b, &token); + material.emission[0] = r; + material.emission[1] = g; + material.emission[2] = b; + continue; + } } - // initial temporary material - InitMaterial(&material); - - has_d = false; - has_tr = false; - - // set new mtl name - token += 7; - { - std::stringstream sstr; - sstr << token; - material.name = sstr.str(); + // transmittance + if ( //(token[0] == 'K' && token[1] == 't') || + token[0] == 'T' && token[1] == 'f') { + token += 2; + real_t r, g, b; + parseReal3(&r, &g, &b, &token); + material.transmittance[0] = r; + material.transmittance[1] = g; + material.transmittance[2] = b; + continue; } - continue; - } - // ambient - if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { - token += 2; - real_t r, g, b; - parseReal3(&r, &g, &b, &token); - material.ambient[0] = r; - material.ambient[1] = g; - material.ambient[2] = b; - continue; - } + // ior(index of refraction) + if (token[0] == 'N' && token[1] == 'i') { + token += 2; + material.ior = parseReal(&token); + continue; + } - // diffuse - if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { - token += 2; - real_t r, g, b; - parseReal3(&r, &g, &b, &token); - material.diffuse[0] = r; - material.diffuse[1] = g; - material.diffuse[2] = b; - continue; - } + // shininess + if (token[0] == 'N' && token[1] == 's') { + token += 2; + material.shininess = parseReal(&token); + continue; + } - // specular - if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { - token += 2; - real_t r, g, b; - parseReal3(&r, &g, &b, &token); - material.specular[0] = r; - material.specular[1] = g; - material.specular[2] = b; - continue; - } + if (token[0] == 'T' && token[1] == 'r') { + token += 2; + if (has_d) { + // `d` wins. Ignore `Tr` value. + ss << "WARN: Both `d` and `Tr` parameters defined for \"" + << material.name << "\". Use the value of `d` for dissolve." + << std::endl; + } else { + // We invert value of Tr(assume Tr is in range [0, 1]) + // NOTE: Interpretation of Tr is application(exporter) dependent. For + // some application(e.g. 3ds max obj exporter), Tr = d(Issue 43) + material.dissolve = 1.0f - parseReal(&token); + } + has_tr = true; + continue; + } - // transmittance - if ((token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) || - (token[0] == 'T' && token[1] == 'f' && IS_SPACE((token[2])))) { - token += 2; - real_t r, g, b; - parseReal3(&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' && IS_SPACE((token[2]))) { - token += 2; - material.ior = parseReal(&token); - continue; - } - - // emission - if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { - token += 2; - real_t r, g, b; - parseReal3(&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' && IS_SPACE(token[2])) { - token += 2; - material.shininess = parseReal(&token); - continue; - } - - // illum model - if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { - token += 6; - material.illum = parseInt(&token); - continue; + // tigra: refactoring for new speedup release + if (token[0] == 'P') { + // PBR: roughness + if (token[1] == 'r') { + token += 2; + material.roughness = parseReal(&token); + continue; + } else + // PBR: metallic + if (token[1] == 'm') { + token += 2; + material.metallic = parseReal(&token); + continue; + } else + // PBR: sheen + if (token[1] == 's') { + token += 2; + material.sheen = parseReal(&token); + continue; + } else + // PBR: clearcoat thickness + if (token[1] == 'c') { + token += 2; + material.clearcoat_thickness = parseReal(&token); + continue; + } + } } // dissolve @@ -1311,206 +1685,232 @@ void LoadMtl(std::map *material_map, has_d = true; continue; } - if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { - token += 2; - if (has_d) { - // `d` wins. Ignore `Tr` value. - ss << "WARN: Both `d` and `Tr` parameters defined for \"" - << material.name << "\". Use the value of `d` for dissolve." - << std::endl; - } else { - // We invert value of Tr(assume Tr is in range [0, 1]) - // NOTE: Interpretation of Tr is application(exporter) dependent. For - // some application(e.g. 3ds max obj exporter), Tr = d(Issue 43) - material.dissolve = 1.0f - parseReal(&token); + + a_tok = token2tok(token); + + // tigra: minimize checks + if (a_tok >= TOK_newmtl && a_tok <= TOK_norm) { + // tigra: refactoring for new speedup release + // new mtl + // if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) + if (a_tok == TOK_newmtl) { + // flush previous material. + if (!material.name.empty()) { + /* + material_map->insert(std::pair( + material.name, static_cast(materials->size())) + ); + */ + + unsigned int hsh1 = X31_hash_string(material.name.c_str()); + + material_map->insert(std::pair( + hsh1, static_cast(materials->size()))); + materials->push_back(material); + } + + // initial temporary material + InitMaterial(&material); + + has_d = false; + has_tr = false; + + // set new mtl name + token += 7; + { + /* + std::stringstream sstr; + sstr << token; + material.name = sstr.str(); + */ + + material.name = std::string(token); + } + continue; } - has_tr = true; - continue; - } - // PBR: roughness - if (token[0] == 'P' && token[1] == 'r' && IS_SPACE(token[2])) { - token += 2; - material.roughness = parseReal(&token); - continue; - } + // illum model + // if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) + if (a_tok == TOK_illum) { + token += 6; + material.illum = parseInt(&token); + continue; + } - // PBR: metallic - if (token[0] == 'P' && token[1] == 'm' && IS_SPACE(token[2])) { - token += 2; - material.metallic = parseReal(&token); - continue; - } + // PBR: clearcoat roughness + // if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) + if (a_tok == TOK_Pcr) { + token += 4; + material.clearcoat_roughness = parseReal(&token); + continue; + } - // PBR: sheen - if (token[0] == 'P' && token[1] == 's' && IS_SPACE(token[2])) { - token += 2; - material.sheen = parseReal(&token); - continue; - } + // PBR: anisotropy + // if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) + if (a_tok == TOK_aniso) { + token += 6; + material.anisotropy = parseReal(&token); + continue; + } - // PBR: clearcoat thickness - if (token[0] == 'P' && token[1] == 'c' && IS_SPACE(token[2])) { - token += 2; - material.clearcoat_thickness = parseReal(&token); - continue; - } + // PBR: anisotropy rotation + // if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) + if (a_tok == TOK_anisor) { + token += 7; + material.anisotropy_rotation = parseReal(&token); + continue; + } - // PBR: clearcoat roughness - if ((0 == strncmp(token, "Pcr", 3)) && IS_SPACE(token[3])) { - token += 4; - material.clearcoat_roughness = parseReal(&token); - continue; - } + // ambient texture + // if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) + if (a_tok == TOK_map_Ka) { + token += 7; + ParseTextureNameAndOption(&(material.ambient_texname), + &(material.ambient_texopt), token, + /* is_bump */ false); + continue; + } - // PBR: anisotropy - if ((0 == strncmp(token, "aniso", 5)) && IS_SPACE(token[5])) { - token += 6; - material.anisotropy = parseReal(&token); - continue; - } + // diffuse texture + // if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) + if (a_tok == TOK_map_Kd) { + token += 7; + ParseTextureNameAndOption(&(material.diffuse_texname), + &(material.diffuse_texopt), token, + /* is_bump */ false); + continue; + } - // PBR: anisotropy rotation - if ((0 == strncmp(token, "anisor", 6)) && IS_SPACE(token[6])) { - token += 7; - material.anisotropy_rotation = parseReal(&token); - continue; - } + // specular texture + // if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) + if (a_tok == TOK_map_Ks) { + token += 7; + ParseTextureNameAndOption(&(material.specular_texname), + &(material.specular_texopt), token, + /* is_bump */ false); + continue; + } - // ambient texture - if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { - token += 7; - ParseTextureNameAndOption(&(material.ambient_texname), - &(material.ambient_texopt), token, - /* is_bump */ false); - continue; - } + // specular highlight texture + // if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) + if (a_tok == TOK_map_Ns) { + token += 7; + ParseTextureNameAndOption(&(material.specular_highlight_texname), + &(material.specular_highlight_texopt), token, + /* is_bump */ false); + continue; + } - // diffuse texture - if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { - token += 7; - ParseTextureNameAndOption(&(material.diffuse_texname), - &(material.diffuse_texopt), token, - /* is_bump */ false); - continue; - } + // bump texture + // if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) + if (a_tok == TOK_map_bump) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } - // specular texture - if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { - token += 7; - ParseTextureNameAndOption(&(material.specular_texname), - &(material.specular_texopt), token, - /* is_bump */ false); - continue; - } + // bump texture + // if ((0 == strncmp(token, "map_Bump", 8)) && IS_SPACE(token[8])) + if (a_tok == TOK_map_Bump) { + token += 9; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } - // specular highlight texture - if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { - token += 7; - ParseTextureNameAndOption(&(material.specular_highlight_texname), - &(material.specular_highlight_texopt), token, - /* is_bump */ false); - continue; - } + // bump texture + // if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) + if (a_tok == TOK_bump) { + token += 5; + ParseTextureNameAndOption(&(material.bump_texname), + &(material.bump_texopt), token, + /* is_bump */ true); + continue; + } - // bump texture - if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { - token += 9; - ParseTextureNameAndOption(&(material.bump_texname), - &(material.bump_texopt), token, - /* is_bump */ true); - continue; - } + // alpha texture + // if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) + if (a_tok == TOK_map_d) { + token += 6; + material.alpha_texname = token; + ParseTextureNameAndOption(&(material.alpha_texname), + &(material.alpha_texopt), token, + /* is_bump */ false); + continue; + } - // bump texture - if ((0 == strncmp(token, "map_Bump", 8)) && IS_SPACE(token[8])) { - token += 9; - ParseTextureNameAndOption(&(material.bump_texname), - &(material.bump_texopt), token, - /* is_bump */ true); - continue; - } + // displacement texture + // if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) + if (a_tok == TOK_disp) { + token += 5; + ParseTextureNameAndOption(&(material.displacement_texname), + &(material.displacement_texopt), token, + /* is_bump */ false); + continue; + } - // bump texture - if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { - token += 5; - ParseTextureNameAndOption(&(material.bump_texname), - &(material.bump_texopt), token, - /* is_bump */ true); - continue; - } + // reflection map + // if ((0 == strncmp(token, "refl", 4)) && IS_SPACE(token[4])) + if (a_tok == TOK_refl) { + token += 5; + ParseTextureNameAndOption(&(material.reflection_texname), + &(material.reflection_texopt), token, + /* is_bump */ false); + continue; + } - // alpha texture - if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { - token += 6; - material.alpha_texname = token; - ParseTextureNameAndOption(&(material.alpha_texname), - &(material.alpha_texopt), token, - /* is_bump */ false); - continue; - } + // PBR: roughness texture + // if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) + if (a_tok == TOK_map_Pr) { + token += 7; + ParseTextureNameAndOption(&(material.roughness_texname), + &(material.roughness_texopt), token, + /* is_bump */ false); + continue; + } - // displacement texture - if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { - token += 5; - ParseTextureNameAndOption(&(material.displacement_texname), - &(material.displacement_texopt), token, - /* is_bump */ false); - continue; - } + // PBR: metallic texture + // if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) + if (a_tok == TOK_map_Pm) { + token += 7; + ParseTextureNameAndOption(&(material.metallic_texname), + &(material.metallic_texopt), token, + /* is_bump */ false); + continue; + } - // reflection map - if ((0 == strncmp(token, "refl", 4)) && IS_SPACE(token[4])) { - token += 5; - ParseTextureNameAndOption(&(material.reflection_texname), - &(material.reflection_texopt), token, - /* is_bump */ false); - continue; - } + // PBR: sheen texture + // if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) + if (a_tok == TOK_map_Ps) { + token += 7; + ParseTextureNameAndOption(&(material.sheen_texname), + &(material.sheen_texopt), token, + /* is_bump */ false); + continue; + } - // PBR: roughness texture - if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { - token += 7; - ParseTextureNameAndOption(&(material.roughness_texname), - &(material.roughness_texopt), token, - /* is_bump */ false); - continue; - } + // PBR: emissive texture + // if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) + if (a_tok == TOK_map_Ke) { + token += 7; + ParseTextureNameAndOption(&(material.emissive_texname), + &(material.emissive_texopt), token, + /* is_bump */ false); + continue; + } - // PBR: metallic texture - if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { - token += 7; - ParseTextureNameAndOption(&(material.metallic_texname), - &(material.metallic_texopt), token, - /* is_bump */ false); - continue; - } - - // PBR: sheen texture - if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { - token += 7; - ParseTextureNameAndOption(&(material.sheen_texname), - &(material.sheen_texopt), token, - /* is_bump */ false); - continue; - } - - // PBR: emissive texture - if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { - token += 7; - ParseTextureNameAndOption(&(material.emissive_texname), - &(material.emissive_texopt), token, - /* is_bump */ false); - continue; - } - - // PBR: normal map texture - if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { - token += 5; - ParseTextureNameAndOption( - &(material.normal_texname), &(material.normal_texopt), token, - /* is_bump */ false); // @fixme { is_bump will be true? } - continue; + // PBR: normal map texture + // if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) + if (a_tok == TOK_norm) { + token += 5; + ParseTextureNameAndOption( + &(material.normal_texname), &(material.normal_texopt), token, + /* is_bump */ false); // @fixme { is_bump will be true? } + continue; + } } // unknown parameter @@ -1526,9 +1926,17 @@ void LoadMtl(std::map *material_map, std::pair(key, value)); } } + + unsigned int hsh1 = X31_hash_string(material.name.c_str()); + // flush last material. + /* material_map->insert(std::pair( material.name, static_cast(materials->size()))); + */ + + material_map->insert( + std::pair(hsh1, static_cast(materials->size()))); materials->push_back(material); if (warning) { @@ -1538,7 +1946,8 @@ void LoadMtl(std::map *material_map, bool MaterialFileReader::operator()(const std::string &matId, std::vector *materials, - std::map *matMap, + // std::map *matMap, + std::map *matMap, std::string *err) { std::string filepath; @@ -1548,7 +1957,14 @@ bool MaterialFileReader::operator()(const std::string &matId, filepath = matId; } +// tigra: add buffered stream +#ifdef TINYOBJLOADER_IMPLEMENTATION_BUFREAD + ImportInBuf buf(filepath.c_str()); + std::istream matIStream(&buf); +#else std::ifstream matIStream(filepath.c_str()); +#endif + if (!matIStream) { std::stringstream ss; ss << "WARN: Material file [ " << filepath << " ] not found." << std::endl; @@ -1572,7 +1988,8 @@ bool MaterialFileReader::operator()(const std::string &matId, bool MaterialStreamReader::operator()(const std::string &matId, std::vector *materials, - std::map *matMap, + // std::map *matMap, + std::map *matMap, std::string *err) { (void)matId; if (!m_inStream) { @@ -1607,7 +2024,14 @@ bool LoadObj(attrib_t *attrib, std::vector *shapes, std::stringstream errss; +// tigra: add buffered stream +#ifdef TINYOBJLOADER_IMPLEMENTATION_BUFREAD + ImportInBuf buf(filename); + std::istream ifs(&buf); +#else std::ifstream ifs(filename); +#endif + if (!ifs) { errss << "Cannot open file [" << filename << "]" << std::endl; if (err) { @@ -1640,8 +2064,17 @@ bool LoadObj(attrib_t *attrib, std::vector *shapes, std::vector > faceGroup; std::string name; + int a_tok; + + // init hashed tokens map + initHashedTokensMap(); + // material - std::map material_map; + // std::map material_map; + + // tigra: key of material_map is unsigned int now + // because std::map is an red-black trees it is better to store key as int + std::map material_map; int material = -1; shape_t shape; @@ -1674,79 +2107,200 @@ bool LoadObj(attrib_t *attrib, std::vector *shapes, if (token[0] == '#') continue; // comment line - // vertex - if (token[0] == 'v' && IS_SPACE((token[1]))) { - token += 2; - vec3_t v3; - real_t r, g, b; - parseVertexWithColor(&v3.x, &v3.y, &v3.z, &r, &g, &b, &token); - v.push_back(v3); + if (IS_SPACE((token[1]))) { + // vertex + if (token[0] == 'v') { + token += 2; + vec3_t vtx; + real_t r, g, b; + parseVertexWithColor(&vtx.x, &vtx.y, &vtx.z, &r, &g, &b, &token); + v.push_back(vtx); - vc.push_back(r); - vc.push_back(g); - vc.push_back(b); - continue; - } + real_t color; + - // normal - if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { - token += 3; - vec3_t v3; - parseReal3(&v3.x, &v3.y, &v3.z, &token); - vn.push_back(v3); - continue; - } - - // texcoord - if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { - token += 3; - vec2_t v2; - parseReal2(&v2.x, &v2.y, &token); - vt.push_back(v2); - continue; - } - - // face - if (token[0] == 'f' && IS_SPACE((token[1]))) { - token += 2; - token += strspn(token, " \t"); - - std::vector face; - face.reserve(3); - - while (!IS_NEW_LINE(token[0])) { - vertex_index vi; - if (!parseTriple(&token, static_cast(v.size()), - static_cast(vn.size()), - static_cast(vt.size()), &vi)) { - if (err) { - (*err) = "Failed parse `f' line(e.g. zero value for face index).\n"; - } - return false; - } - - face.push_back(vi); - size_t n = strspn(token, " \t\r"); - token += n; + vc.push_back(r); + vc.push_back(g); + vc.push_back(b); + continue; } - // replace with emplace_back + std::move on C++11 - faceGroup.push_back(std::vector()); - faceGroup[faceGroup.size() - 1].swap(face); + // face + if (token[0] == 'f') { + token += 2; + token += strspn(token, " \t"); - continue; + std::vector face; + face.reserve(3); + + while (!IS_NEW_LINE(token[0])) { + vertex_index vi; + if (!parseTriple(&token, static_cast(v.size() / 3), + static_cast(vn.size() / 3), + static_cast(vt.size() / 2), &vi)) { + if (err) { + (*err) = + "Failed parse `f' line(e.g. zero value for face index).\n"; + } + return false; + } + + face.push_back(vi); + size_t n = strspn(token, " \t\r"); + token += n; + } + + // replace with emplace_back + std::move on C++11 + faceGroup.push_back(std::vector()); + faceGroup[faceGroup.size() - 1].swap(face); + + continue; + } + + // group name + if (token[0] == 'g') { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, + name, triangulate, v); + (void)ret; // return value not used. + + if (shape.mesh.indices.size() > 0) { + shapes->push_back(shape); + } + + shape = shape_t(); + + // material = -1; + faceGroup.clear(); + + std::vector names; + names.reserve(2); + + while (!IS_NEW_LINE(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 skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } + + continue; + } + + // object name + if (token[0] == 'o') { + // flush previous face group. + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, + name, triangulate, v); + if (ret) { + shapes->push_back(shape); + } + + // material = -1; + faceGroup.clear(); + shape = shape_t(); + + // @todo { multiple object name? } + token += 2; + + /* + std::stringstream ss; + ss << token; + name = ss.str(); + */ + + name = std::string(token); + + continue; + } + + if (token[0] == 't') { + tag_t tag; + + token += 2; + + tag.name = parseString(&token); + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = parseInt(&token); + } + + tag.floatValues.resize(static_cast(ts.num_reals)); + for (size_t i = 0; i < static_cast(ts.num_reals); ++i) { + tag.floatValues[i] = parseReal(&token); + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + tag.stringValues[i] = parseString(&token); + } + + tags.push_back(tag); + } } + if (token[0] == 'v' && IS_SPACE((token[2]))) { + // normal + if (token[1] == 'n') { + token += 3; + vec3_t n; + parseReal3(&n.x, &n.y, &n.z, &token); + vn.push_back(n); + continue; + } + + // texcoord + if (token[1] == 't') { + token += 3; + vec2_t tcoord; + parseReal2(&tcoord.x, &tcoord.y, &token); + vt.push_back(tcoord); + continue; + } + } + + // tigra: refactoring for new speedup release + // tigra: compares one more start + + a_tok = token2tok(token); + // use mtl - if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + // if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) + if (a_tok == TOK_usemtl) { token += 7; - std::stringstream ss; - ss << token; - std::string namebuf = ss.str(); + /* + std::stringstream ss; + ss << token; + std::string namebuf = ss.str(); + */ + + /* + std::string namebuf = std::string(token); + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + */ + + unsigned int hsh = X31_hash_string(token); int newMaterialId = -1; - if (material_map.find(namebuf) != material_map.end()) { - newMaterialId = material_map[namebuf]; + if (material_map.find(hsh) != material_map.end()) { + newMaterialId = material_map[hsh]; } else { // { error!! material not found } } @@ -1765,7 +2319,8 @@ bool LoadObj(attrib_t *attrib, std::vector *shapes, } // load mtl - if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + // if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) + if (a_tok == TOK_mtllib) { if (readMatFn) { token += 7; @@ -1806,93 +2361,8 @@ bool LoadObj(attrib_t *attrib, std::vector *shapes, continue; } - - // group name - if (token[0] == 'g' && IS_SPACE((token[1]))) { - // flush previous face group. - bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, - triangulate, v); - (void)ret; // return value not used. - - if (shape.mesh.indices.size() > 0) { - shapes->push_back(shape); - } - - shape = shape_t(); - - // material = -1; - faceGroup.clear(); - - std::vector names; - names.reserve(2); - - while (!IS_NEW_LINE(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 skip the 0th element. - if (names.size() > 1) { - name = names[1]; - } else { - name = ""; - } - - continue; - } - - // object name - if (token[0] == 'o' && IS_SPACE((token[1]))) { - // flush previous face group. - bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, - triangulate, v); - if (ret) { - shapes->push_back(shape); - } - - // material = -1; - faceGroup.clear(); - shape = shape_t(); - - // @todo { multiple object name? } - token += 2; - std::stringstream ss; - ss << token; - name = ss.str(); - - continue; - } - - if (token[0] == 't' && IS_SPACE(token[1])) { - tag_t tag; - - token += 2; - - tag.name = parseString(&token); - - tag_sizes ts = parseTagTriple(&token); - - tag.intValues.resize(static_cast(ts.num_ints)); - - for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { - tag.intValues[i] = parseInt(&token); - } - - tag.floatValues.resize(static_cast(ts.num_reals)); - for (size_t i = 0; i < static_cast(ts.num_reals); ++i) { - tag.floatValues[i] = parseReal(&token); - } - - tag.stringValues.resize(static_cast(ts.num_strings)); - for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { - tag.stringValues[i] = parseString(&token); - } - - tags.push_back(tag); - } + // tigra: compares one more END + // tigra: refactoring for new speedup release // Ignore unknown command. } @@ -1926,8 +2396,14 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, std::string *err /*= NULL*/) { std::stringstream errss; + int a_tok; + + // init hashed tokens map + initHashedTokensMap(); + // material - std::map material_map; + // std::map material_map; + std::map material_map; int material_id = -1; // -1 = invalid std::vector indices; @@ -2026,16 +2502,145 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, continue; } - // use mtl - if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { - token += 7; + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + names.clear(); + + while (!IS_NEW_LINE(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 skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name.clear(); + } + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + names_out.resize(names.size() - 1); + for (size_t j = 0; j < names_out.size(); j++) { + names_out[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &names_out.at(0), + static_cast(names_out.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + token += 2; + + /* + std::stringstream ss; + ss << token; + std::string object_name = ss.str(); + + if (callback.object_cb) { + callback.object_cb(user_data, object_name.c_str()); + } + */ + + if (callback.object_cb) { + callback.object_cb(user_data, token); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + token += 2; + /* std::stringstream ss; ss << token; - std::string namebuf = ss.str(); + tag.name = ss.str(); + */ + + tag.name = std::string(token); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_reals)); + for (size_t i = 0; i < static_cast(ts.num_reals); ++i) { + tag.floatValues[i] = parseReal(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + + /* + std::stringstream ss; + ss << token; + tag.stringValues[i] = ss.str(); + */ + + tag.stringValues[i] = std::string(token); + + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); + } +#endif + + // tigra: refactoring for new speedup release + // tigra: compares start + + a_tok = token2tok(token); + + // use mtl + // if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) + if (a_tok == TOK_usemtl) { + token += 7; + /* + std::stringstream ss; + ss << token; + std::string namebuf = ss.str(); + */ + + /* + std::string namebuf = std::string(token); + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + */ + + // make a hash from token + unsigned int hsh = X31_hash_string(token); int newMaterialId = -1; - if (material_map.find(namebuf) != material_map.end()) { - newMaterialId = material_map[namebuf]; + if (material_map.find(hsh) != material_map.end()) { + newMaterialId = material_map[hsh]; } else { // { error!! material not found } } @@ -2045,14 +2650,16 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, } if (callback.usemtl_cb) { - callback.usemtl_cb(user_data, namebuf.c_str(), material_id); + // callback.usemtl_cb(user_data, namebuf.c_str(), material_id); + callback.usemtl_cb(user_data, token, material_id); } continue; } // load mtl - if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + // if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) + if (a_tok == TOK_mtllib) { if (readMatFn) { token += 7; @@ -2098,97 +2705,8 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback, continue; } - - // group name - if (token[0] == 'g' && IS_SPACE((token[1]))) { - names.clear(); - - while (!IS_NEW_LINE(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 skip the 0th element. - if (names.size() > 1) { - name = names[1]; - } else { - name.clear(); - } - - if (callback.group_cb) { - if (names.size() > 1) { - // create const char* array. - names_out.resize(names.size() - 1); - for (size_t j = 0; j < names_out.size(); j++) { - names_out[j] = names[j + 1].c_str(); - } - callback.group_cb(user_data, &names_out.at(0), - static_cast(names_out.size())); - - } else { - callback.group_cb(user_data, NULL, 0); - } - } - - continue; - } - - // object name - if (token[0] == 'o' && IS_SPACE((token[1]))) { - // @todo { multiple object name? } - token += 2; - - std::stringstream ss; - ss << token; - std::string object_name = ss.str(); - - if (callback.object_cb) { - callback.object_cb(user_data, object_name.c_str()); - } - - continue; - } - -#if 0 // @todo - if (token[0] == 't' && IS_SPACE(token[1])) { - tag_t tag; - - token += 2; - std::stringstream ss; - ss << token; - tag.name = ss.str(); - - token += tag.name.size() + 1; - - tag_sizes ts = parseTagTriple(&token); - - tag.intValues.resize(static_cast(ts.num_ints)); - - for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { - tag.intValues[i] = atoi(token); - token += strcspn(token, "/ \t\r") + 1; - } - - tag.floatValues.resize(static_cast(ts.num_reals)); - for (size_t i = 0; i < static_cast(ts.num_reals); ++i) { - tag.floatValues[i] = parseReal(&token); - token += strcspn(token, "/ \t\r") + 1; - } - - tag.stringValues.resize(static_cast(ts.num_strings)); - for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { - std::stringstream ss; - ss << token; - tag.stringValues[i] = ss.str(); - token += tag.stringValues[i].size() + 1; - } - - tags.push_back(tag); - } -#endif + // tigra: compares end + // tigra: refactoring for new speedup release // Ignore unknown command. }