//MTL PARSER INSPIRED FROM KIXOR.NET "objloader" (http://www.kixor.net/dev/objloader/) bool ccMaterialSet::ParseMTL(QString path, const QString& filename, ccMaterialSet &materials, QStringList& errors) { //open mtl file QFile file(path+QString('/')+filename); if (!file.open(QFile::ReadOnly)) { errors << QString("Error reading file: %1").arg(filename); return false; } QTextStream stream(&file); QString currentLine = stream.readLine(); unsigned currentLineIndex = 0; int currentMatIndex = -1; ccMaterial currentMaterial; while( !currentLine.isNull() ) { ++currentLineIndex; QStringList tokens = currentLine.split(QRegExp("\\s+"),QString::SkipEmptyParts); //skip comments & empty lines if( tokens.empty() || tokens.front().startsWith('/',Qt::CaseInsensitive) || tokens.front().startsWith('#',Qt::CaseInsensitive) ) { currentLine = stream.readLine(); continue; } //start material if (tokens.front() == "newmtl") { //push the precedent material if (currentMatIndex >= 0) materials.addMaterial(currentMaterial); ++currentMatIndex; currentMaterial = ccMaterial(); //materials.resize(materials.size()+1); // get the name currentMaterial.name = (tokens.size()>1 ? tokens[1] : "undefined"); } else if (currentMatIndex>=0) //we already have a "current" material { //ambient if (tokens.front() == "Ka") { if (tokens.size() > 3) { currentMaterial.ambient[0] = tokens[1].toFloat(); currentMaterial.ambient[1] = tokens[2].toFloat(); currentMaterial.ambient[2] = tokens[3].toFloat(); } } //diff else if (tokens.front() == "Kd") { if (tokens.size() > 3) { currentMaterial.diffuseFront[0] = tokens[1].toFloat(); currentMaterial.diffuseFront[1] = tokens[2].toFloat(); currentMaterial.diffuseFront[2] = tokens[3].toFloat(); //duplicate memcpy(currentMaterial.diffuseBack,currentMaterial.diffuseFront,sizeof(float)*3); } } //specular else if (tokens.front() == "Ks") { if (tokens.size() > 3) { currentMaterial.specular[0] = tokens[1].toFloat(); currentMaterial.specular[1] = tokens[2].toFloat(); currentMaterial.specular[2] = tokens[3].toFloat(); } } //shiny else if (tokens.front() == "Ns") { if (tokens.size() > 1) currentMaterial.setShininess(tokens[1].toFloat()); } //transparent else if (tokens.front() == "d" || tokens.front() == "Tr") { if (tokens.size() > 1) currentMaterial.setTransparency(tokens[1].toFloat()); } //reflection else if (tokens.front() == "r") { //ignored //if (tokens.size() > 1) // currentMaterial.reflect = tokens[1].toFloat(); } //glossy else if (tokens.front() == "sharpness") { //ignored //if (tokens.size() > 1) // currentMaterial.glossy = tokens[1].toFloat(); } //refract index else if (tokens.front() == "Ni") { //ignored //if (tokens.size() > 1) // currentMaterial.refract_index = tokens[1].toFloat(); } // illumination type else if (tokens.front() == "illum") { //ignored } // texture map else if (tokens.front() == "map_Ka" || tokens.front() == "map_Kd" || tokens.front() == "map_Ks") { QString texture_filename = currentLine.mid(7).trimmed(); QString fullTexName = path+QString('/')+texture_filename; QImage image; if (!image.load(fullTexName)) { errors << QString("Failed to load texture file: %1").arg(fullTexName); } else { currentMaterial.texture = image.mirrored(); //mirrored = WTF?! } } else { errors << QString("Unknown command '%1' at line %2").arg(tokens.front()).arg(currentLineIndex); } } currentLine = stream.readLine(); } file.close(); //push the last material if (currentMatIndex >= 0) materials.addMaterial(currentMaterial); return true; }
//MTL PARSER INSPIRED FROM KIXOR.NET "objloader" (http://www.kixor.net/dev/objloader/) bool ccMaterialSet::ParseMTL(QString path, const QString& filename, ccMaterialSet &materials, QStringList& errors) { //open mtl file QString fullPathFilename = path + QString('/') + filename; QFile file(fullPathFilename); if (!file.open(QFile::ReadOnly)) { errors << QString("Error reading file: %1").arg(filename); return false; } //update path (if the input filename has already a relative path) path = QFileInfo(fullPathFilename).absolutePath(); QTextStream stream(&file); QString currentLine = stream.readLine(); unsigned currentLineIndex = 0; ccMaterial::Shared currentMaterial(0); while( !currentLine.isNull() ) { ++currentLineIndex; QStringList tokens = currentLine.split(QRegExp("\\s+"),QString::SkipEmptyParts); //skip comments & empty lines if( tokens.empty() || tokens.front().startsWith('/',Qt::CaseInsensitive) || tokens.front().startsWith('#',Qt::CaseInsensitive) ) { currentLine = stream.readLine(); continue; } //start material if (tokens.front() == "newmtl") { //push the previous material (if any) if (currentMaterial) { materials.addMaterial(currentMaterial); currentMaterial = ccMaterial::Shared(0); } // get the name QString materialName = currentLine.mid(7).trimmed(); //we must take the whole line! (see OBJ filter) if (materialName.isEmpty()) materialName = "undefined"; currentMaterial = ccMaterial::Shared(new ccMaterial(materialName)); } else if (currentMaterial) //we already have a "current" material { //ambient if (tokens.front() == "Ka") { if (tokens.size() > 3) { ccColor::Rgbaf ambient( tokens[1].toFloat(), tokens[2].toFloat(), tokens[3].toFloat(), 1.0f); currentMaterial->setAmbient(ambient); } } //diff else if (tokens.front() == "Kd") { if (tokens.size() > 3) { ccColor::Rgbaf diffuse( tokens[1].toFloat(), tokens[2].toFloat(), tokens[3].toFloat(), 1.0f); currentMaterial->setDiffuse(diffuse); } } //specular else if (tokens.front() == "Ks") { if (tokens.size() > 3) { ccColor::Rgbaf specular(tokens[1].toFloat(), tokens[2].toFloat(), tokens[3].toFloat(), 1.0f); currentMaterial->setSpecular(specular); } } //shiny else if (tokens.front() == "Ns") { if (tokens.size() > 1) currentMaterial->setShininess(tokens[1].toFloat()); } //transparent else if (tokens.front() == "d" || tokens.front() == "Tr") { if (tokens.size() > 1) currentMaterial->setTransparency(tokens[1].toFloat()); } //reflection else if (tokens.front() == "r") { //ignored //if (tokens.size() > 1) // currentMaterial->reflect = tokens[1].toFloat(); } //glossy else if (tokens.front() == "sharpness") { //ignored //if (tokens.size() > 1) // currentMaterial->glossy = tokens[1].toFloat(); } //refract index else if (tokens.front() == "Ni") { //ignored //if (tokens.size() > 1) // currentMaterial->refract_index = tokens[1].toFloat(); } // illumination type else if (tokens.front() == "illum") { //ignored } // texture map else if (tokens.front() == "map_Ka" || tokens.front() == "map_Kd" || tokens.front() == "map_Ks") { //DGM: in case there's hidden or space characters at the beginning of the line... int shift = currentLine.indexOf("map_K",0); QString textureFilename = (shift + 7 < currentLine.size() ? currentLine.mid(shift+7).trimmed() : QString()); QString fullTexName = path + QString('/') + textureFilename; if (!currentMaterial->loadAndSetTexture(fullTexName)) { errors << QString("Failed to load texture file: %1").arg(fullTexName); } } else { errors << QString("Unknown command '%1' at line %2").arg(tokens.front()).arg(currentLineIndex); } } currentLine = stream.readLine(); } file.close(); //don't forget to push the last material! if (currentMaterial) materials.addMaterial(currentMaterial); return true; }