pushrbx icon

Untitled

pushrbx | PRO | 04/25/13 07:41:57 PM UTC | 0 ⭐ | 359 👁️ | Never ⏰ | []
C++ |

3.46 KB

|

None

|

0 👍

/

0 👎

void CObjMeshParser::parse(shared_ptr<CMesh>& pMesh, const string& strFileName)
{
    //  usefull to retrieve material files
    {
        const path filePath(strFileName);
        m_branchPath = filePath.branch_path();
    }
 
    ifstream ifs(strFileName.c_str(), ios::in|ios::ate);
    if (!ifs)
        throw(CFileNotFoundException(strFileName));
 
    const int fileSize = ifs.tellg();    //  get the file size (we started at the end)...
    ifs.seekg (0, ios::beg);  //  ...then get back to start
    
    if (0 == fileSize)
        throw CEmptyFileException();
 
    //  explain what's going on
    CLogger::get() << "Parsing file \"" << strFileName << "\" (file size = " << fileSize << " bytes)...\n" << flush;
    
    // do a bit of cleaning before adding data in case the mesh was used before.
    pMesh->clear();
 
    // and go.
    int percent = 10;   //  progress indicator
    while(skipCommentLine(ifs)) 
    {
        // show progress for files larger than one Mo
        if ((fileSize > 1024*1024) && (100*ifs.tellg()/fileSize >= percent)) {
            percent = 100*ifs.tellg()/fileSize;
            percent = (percent/10)*10;
            CLogger::get() << "  " << percent << " % done...\n" << flush;
            percent += 10;
        }
            
        if (false == processLine(pMesh, ifs))
            break;
    }
}
 
bool CObjMeshParser::skipCommentLine(istream& is)
{
    char next;
    while( is >> std::skipws >> next ) 
    {
        is.putback(next);
        if ('#' == next)
            skipLine(is);
        else
            return true;
    }
    return false;
}
 
bool CObjMeshParser::processLine(shared_ptr<CMesh>& pMesh, istream& is)
{
    string ele_id;
    float x, y, z;
    
    if (!(is >> ele_id))
        return false;
    
    if ("mtllib" == ele_id) {
        string strFileName;
        is >> strFileName;
        parseMtlLib(strFileName);
    }
    else if ("usemtl" == ele_id) {
        string strMtlName;
        is >> strMtlName;
        map<string, SMaterial>::iterator it = m_materialMap.find(strMtlName);
        if (it != m_materialMap.end())
            pMesh->setMaterial((*it).second);
        else
            CLogger::get() << "  * Material not found in current mtllib :\"" << strMtlName << "\". Ignoring material.\n";
    }
    else if ("v" == ele_id) {   //  vertex data
        is >> x >> y >> z;
        pMesh->addVertex(SVertex(x, y, z));
    }
    else if ("vt" == ele_id) {  // texture data
        is >> x >> y >> z;
        is.clear();                           // is z (i.e. w) is not available, have to clear error flag.
        pMesh->addTextureCoord(SVertex(x, y, z));
    }
    else if ("vn" == ele_id) {  // normal data
        is >> x >> y >> z;
        if(!is.good()) {                     // in case it is -1#IND00
            x = y = z = 0.0;
            is.clear();
            skipLine(is);
        }
        pMesh->addNormal(SVertex(x, y, z));
    }
    else if ("f" == ele_id) {   //  face data
                                //  face treatment
                                //  Note: obviously this technique only works for convex polygons with ten verts or less.
        int vi[10];                               // vertex indices.
        int ni[10] = { -1, -1, -1, -1, };         // normal indices.
        int ti[10] = { -1, -1, -1, -1, };         // tex indices.
        int i = 0;
        for (char c; i<10; ++i) {
            if(!pMesh->hasTextureCoords() && !pMesh->hasNormals())
                is >> vi[i];
            else if(!pMesh->hasTextureCoords())
                is >> vi[i] >> c >> c >> ni[i];
            else if(!pMesh->hasNormals())
                is >> vi[i] >> c >> ti[i];
            else
                is >> vi[i] >> c >> ti[i] >> c >>  ni[i];
            
            if(!is.good())
                break;
        }
        //  Create the polygon face
        SPolygonFace face;
        for (int k=0; k < i; ++k)
            face.addVertTexNorm(vi[k], ti[k], ni[k]);
        pMesh->addFace(face);
        
        is.clear();
    }
    else
        skipLine(is);
    return true;
}

Comments