// ------------------------------------------------------------------------------------------------ void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo) { if(nfo.version > 8) { return UnsupportedChunk_Ascii(splitter,nfo,"Mat1"); } ++splitter; if (!splitter.match_start("mat# ")) { ASSIMP_LOG_WARN_F( "Expected `mat#` line in `Mat1` chunk ", nfo.id ); return; } out.materials.push_back(Material()); Material& mat = out.materials.back(); mat = nfo; mat.matnum = strtoul10(splitter[1]); ++splitter; if (!splitter.match_start("shader: ")) { ASSIMP_LOG_WARN_F( "Expected `mat#` line in `Mat1` chunk ", nfo.id); return; } std::string shader = std::string(splitter[1]); shader = shader.substr(0,shader.find_first_of(" \t")); if (shader == "metal") { mat.shader = Material::METAL; } else if (shader == "phong") { mat.shader = Material::PHONG; } else if (shader != "flat") { ASSIMP_LOG_WARN_F( "Unknown value for `shader` in `Mat1` chunk ", nfo.id ); } ++splitter; if (!splitter.match_start("rgb ")) { ASSIMP_LOG_WARN_F( "Expected `rgb` line in `Mat1` chunk ", nfo.id); } const char* rgb = splitter[1]; ReadFloat3Tuple_Ascii(mat.rgb,&rgb); ++splitter; if (!splitter.match_start("alpha ")) { ASSIMP_LOG_WARN_F( "Expected `alpha` line in `Mat1` chunk ", nfo.id); } const char* tokens[10]; splitter.get_tokens(tokens); mat.alpha = fast_atof( tokens[1] ); mat.ka = fast_atof( tokens[3] ); mat.ks = fast_atof( tokens[5] ); mat.exp = fast_atof( tokens[7] ); mat.ior = fast_atof( tokens[9] ); }
// ------------------------------------------------------------------------------------------------ void COBImporter::ReadLght_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo) { if(nfo.version > 8) { return UnsupportedChunk_Ascii(splitter,nfo,"Lght"); } out.nodes.push_back(std::shared_ptr<Light>(new Light())); Light& msh = (Light&)(*out.nodes.back().get()); msh = nfo; ReadBasicNodeInfo_Ascii(msh,++splitter,nfo); if (splitter.match_start("Infinite ")) { msh.ltype = Light::INFINITE; } else if (splitter.match_start("Local ")) { msh.ltype = Light::LOCAL; } else if (splitter.match_start("Spot ")) { msh.ltype = Light::SPOT; } else { LogWarn_Ascii(splitter,format()<< "Unknown kind of light source in `Lght` chunk "<<nfo.id<<" : "<<*splitter); msh.ltype = Light::SPOT; } ++splitter; if (!splitter.match_start("color ")) { LogWarn_Ascii(splitter,format()<< "Expected `color` line in `Lght` chunk "<<nfo.id); } const char* rgb = splitter[1]; ReadFloat3Tuple_Ascii(msh.color ,&rgb); SkipSpaces(&rgb); if (strncmp(rgb,"cone angle",10)) { LogWarn_Ascii(splitter,format()<< "Expected `cone angle` entity in `color` line in `Lght` chunk "<<nfo.id); } SkipSpaces(rgb+10,&rgb); msh.angle = fast_atof(&rgb); SkipSpaces(&rgb); if (strncmp(rgb,"inner angle",11)) { LogWarn_Ascii(splitter,format()<< "Expected `inner angle` entity in `color` line in `Lght` chunk "<<nfo.id); } SkipSpaces(rgb+11,&rgb); msh.inner_angle = fast_atof(&rgb); // skip the rest for we can't handle this kind of physically-based lighting information. }
// ------------------------------------------------------------------------------------------------ void COBImporter::ReadUnit_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo) { if(nfo.version > 1) { return UnsupportedChunk_Ascii(splitter,nfo,"Unit"); } ++splitter; if (!splitter.match_start("Units ")) { LogWarn_Ascii(splitter,format()<< "Expected `Units` line in `Unit` chunk "<<nfo.id); return; } // parent chunks preceede their childs, so we should have the // corresponding chunk already. for(std::shared_ptr< Node >& nd : out.nodes) { if (nd->id == nfo.parent_id) { const unsigned int t=strtoul10(splitter[1]); nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?( LogWarn_Ascii(splitter,format()<<t<<" is not a valid value for `Units` attribute in `Unit chunk` "<<nfo.id) ,1.f):units[t]; return; } } LogWarn_Ascii(splitter,format()<<"`Unit` chunk "<<nfo.id<<" is a child of " <<nfo.parent_id<<" which does not exist"); }
// ------------------------------------------------------------------------------------------------ void COBImporter::UnsupportedChunk_Ascii(LineSplitter& splitter, const ChunkInfo& nfo, const char* name) { const std::string error = format("Encountered unsupported chunk: ") << name << " [version: "<<nfo.version<<", size: "<<nfo.size<<"]"; // we can recover if the chunk size was specified. if(nfo.size != static_cast<unsigned int>(-1)) { DefaultLogger::get()->error(error); // (HACK) - our current position in the stream is the beginning of the // head line of the next chunk. That's fine, but the caller is going // to call ++ on `splitter`, which we need to swallow to avoid // missing the next line. splitter.get_stream().IncPtr(nfo.size); splitter.swallow_next_increment(); } else ThrowException(error); }
// ------------------------------------------------------------------------------------------------ void COBImporter::ReadChunkInfo_Ascii(ChunkInfo& out, const LineSplitter& splitter) { const char* all_tokens[8]; splitter.get_tokens(all_tokens); out.version = (all_tokens[1][1]-'0')*100+(all_tokens[1][3]-'0')*10+(all_tokens[1][4]-'0'); out.id = strtoul10(all_tokens[3]); out.parent_id = strtoul10(all_tokens[5]); out.size = strtol10(all_tokens[7]); }
// ------------------------------------------------------------------------------------------------ void COBImporter::ReadBasicNodeInfo_Ascii(Node& msh, LineSplitter& splitter, const ChunkInfo& /*nfo*/) { for(;splitter;++splitter) { if (splitter.match_start("Name")) { msh.name = std::string(splitter[1]); // make nice names by merging the dupe count std::replace(msh.name.begin(),msh.name.end(), ',','_'); } else if (splitter.match_start("Transform")) { for(unsigned int y = 0; y < 4 && ++splitter; ++y) { const char* s = splitter->c_str(); for(unsigned int x = 0; x < 4; ++x) { SkipSpaces(&s); msh.transform[y][x] = fast_atof(&s); } } // we need the transform chunk, so we won't return until we have it. return; } } }
// ------------------------------------------------------------------------------------------------ void COBImporter::ReadPolH_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo) { if(nfo.version > 8) { return UnsupportedChunk_Ascii(splitter,nfo,"PolH"); } out.nodes.push_back(std::shared_ptr<Mesh>(new Mesh())); Mesh& msh = (Mesh&)(*out.nodes.back().get()); msh = nfo; ReadBasicNodeInfo_Ascii(msh,++splitter,nfo); // the chunk has a fixed order of components, but some are not interesting of us so // we're just looking for keywords in arbitrary order. The end of the chunk is // either the last `Face` or the `DrawFlags` attribute, depending on the format ver. for(;splitter;++splitter) { if (splitter.match_start("World Vertices")) { const unsigned int cnt = strtoul10(splitter[2]); msh.vertex_positions.resize(cnt); for(unsigned int cur = 0;cur < cnt && ++splitter;++cur) { const char* s = splitter->c_str(); aiVector3D& v = msh.vertex_positions[cur]; SkipSpaces(&s); v.x = fast_atof(&s); SkipSpaces(&s); v.y = fast_atof(&s); SkipSpaces(&s); v.z = fast_atof(&s); } } else if (splitter.match_start("Texture Vertices")) { const unsigned int cnt = strtoul10(splitter[2]); msh.texture_coords.resize(cnt); for(unsigned int cur = 0;cur < cnt && ++splitter;++cur) { const char* s = splitter->c_str(); aiVector2D& v = msh.texture_coords[cur]; SkipSpaces(&s); v.x = fast_atof(&s); SkipSpaces(&s); v.y = fast_atof(&s); } } else if (splitter.match_start("Faces")) { const unsigned int cnt = strtoul10(splitter[1]); msh.faces.reserve(cnt); for(unsigned int cur = 0; cur < cnt && ++splitter ;++cur) { if (splitter.match_start("Hole")) { LogWarn_Ascii(splitter,"Skipping unsupported `Hole` line"); continue; } if (!splitter.match_start("Face")) { ThrowException("Expected Face line"); } msh.faces.push_back(Face()); Face& face = msh.faces.back(); face.indices.resize(strtoul10(splitter[2])); face.flags = strtoul10(splitter[4]); face.material = strtoul10(splitter[6]); const char* s = (++splitter)->c_str(); for(size_t i = 0; i < face.indices.size(); ++i) { if(!SkipSpaces(&s)) { ThrowException("Expected EOL token in Face entry"); } if ('<' != *s++) { ThrowException("Expected < token in Face entry"); } face.indices[i].pos_idx = strtoul10(s,&s); if (',' != *s++) { ThrowException("Expected , token in Face entry"); } face.indices[i].uv_idx = strtoul10(s,&s); if ('>' != *s++) { ThrowException("Expected < token in Face entry"); } } } if (nfo.version <= 4) { break; } } else if (splitter.match_start("DrawFlags")) { msh.draw_flags = strtoul10(splitter[1]); break; } } }
// ------------------------------------------------------------------------------------------------ void COBImporter::LogDebug_Ascii(const LineSplitter& splitter, const format& message) { LogDebug_Ascii(message << " [at line "<< splitter.get_index()<<"]"); }