glc_objmtlloader.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 
00003  This file is part of the GLC-lib library.
00004  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
00005  Version 2.0.0, packaged on July 2010.
00006 
00007  http://glc-lib.sourceforge.net
00008 
00009  GLC-lib is free software; you can redistribute it and/or modify
00010  it under the terms of the GNU Lesser General Public License as published by
00011  the Free Software Foundation; either version 3 of the License, or
00012  (at your option) any later version.
00013 
00014  GLC-lib is distributed in the hope that it will be useful,
00015  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  GNU Lesser General Public License for more details.
00018 
00019  You should have received a copy of the GNU Lesser General Public License
00020  along with GLC-lib; if not, write to the Free Software
00021  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022 
00023 *****************************************************************************/
00024 
00026 
00027 #include "glc_objmtlloader.h"
00028 #include "../glc_fileformatexception.h"
00029 #include <QDir>
00030 #include <QFile>
00031 #include <QTextStream>
00032 #include <QtDebug>
00033 #include <QGLContext>
00034 
00035 GLC_ObjMtlLoader::GLC_ObjMtlLoader(const QString& fileName)
00036 : m_FileName(fileName)
00037 , m_pCurrentMaterial(NULL)
00038 , m_Materials()
00039 , m_LoadStatus()
00040 , m_ListOfAttachedFileName()
00041 {
00042 }
00043 
00044 GLC_ObjMtlLoader::~GLC_ObjMtlLoader()
00045 {
00046         // Remove unused material
00047         QHash<QString, GLC_Material*>::iterator i;
00048         for (i= m_Materials.begin(); i != m_Materials.end(); ++i)
00049         {
00050                 if (i.value()->isUnused()) delete i.value();
00051         }
00052         m_Materials.clear();
00053         m_ListOfAttachedFileName.clear();
00054 }
00056 // Get functions
00058 // Get a material from is name
00059 GLC_Material* GLC_ObjMtlLoader::material(const QString& materialName)
00060 {
00061         if (m_Materials.contains(materialName))
00062         {
00063                 return m_Materials[materialName];
00064         }
00065         else
00066         {
00067                 return NULL;
00068         }
00069 }
00070 
00072 // Set functions
00074 // Load the materials
00075 bool GLC_ObjMtlLoader::loadMaterials()
00076 {
00077 
00078         // Create the input file stream
00079         QFile mtlFile(m_FileName);
00080 
00081         if (!mtlFile.open(QIODevice::ReadOnly))
00082         {
00083                 qDebug() << "GLC_ObjMtlLoader::LoadMaterial File " << m_FileName << " doesn't exist";
00084                 return false;
00085         }
00086         else
00087         {
00088                 //qDebug() << "GLC_ObjMtlLoader::LoadMaterial OK File " << m_FileName << " exist";
00089         }
00090 
00091         QTextStream mtlStream(&mtlFile);
00092 
00093         QString lineBuff;
00094         QString header;
00095 
00096         while (!mtlStream.atEnd())
00097         {
00098                 lineBuff= mtlStream.readLine();
00099                 //qDebug() << lineBuff;
00100                 QTextStream streamLine(lineBuff.toAscii());
00101 
00102                 if ((streamLine >> header).status() ==QTextStream::Ok)
00103                 {
00104 
00105                         // Search New material
00106                         if (header =="newmtl")
00107                         {
00108                                 //qDebug() << "New material find";
00109 
00110                                 if (NULL != m_pCurrentMaterial)
00111                                 {       // It's not the first material
00112                                         //qDebug() << "Add material : " << m_pCurrentMaterial->name();
00113                                         processMayaSpecific();
00114                                         m_Materials.insert(m_pCurrentMaterial->name(), m_pCurrentMaterial);
00115                                         m_pCurrentMaterial= NULL;
00116                                 }
00117 
00118                                 m_pCurrentMaterial= new GLC_Material;
00119                                 if (!extractMaterialName(lineBuff)) return false;
00120                                 //qDebug() << "New Material " << m_pCurrentMaterial->name();
00121 
00122                         }
00123                         else if ((header == "Ka") || (header == "Kd") || (header == "Ks")) // ambiant, diffuse and specular color
00124                         {
00125                                 if (!extractRGBValue(lineBuff)) return false;
00126                         }
00127 
00128                         else if ((header == "Ns") || (header == "d"))   // shiness Or transparency
00129                         {
00130                                 if (!extractOneValue(lineBuff)) return false;
00131                         }
00132                         else if ((header == "map_Kd") || (header == "map_Ka"))  // Texture
00133                         {
00134                                 //qDebug() << "Texture detected";
00135                                 extractTextureFileName(lineBuff);
00136                         }
00137 
00138                 }
00139         }
00140 
00141         if (NULL != m_pCurrentMaterial)
00142         {
00143                 //qDebug() << "Add material : " << m_pCurrentMaterial->name();
00144                 m_Materials.insert(m_pCurrentMaterial->name(), m_pCurrentMaterial);
00145                 m_pCurrentMaterial= NULL;
00146         }
00147 
00148         mtlFile.close();
00149         return true;
00150 
00151 }
00153 // Private services functions
00155 
00156 // Extract the material name
00157 bool GLC_ObjMtlLoader::extractMaterialName(QString &ligne)
00158 {
00159         bool result= false;
00160         QTextStream stream(&ligne);
00161         QString valueString;
00162         QString header;
00163         if ((stream >> header >> valueString).status() == QTextStream::Ok)
00164         {
00165                 // If There is an space in the string to extracts
00166                 QString valueString2;
00167                 while ((stream >> valueString2).status() == QTextStream::Ok)
00168                 {
00169                         valueString.append(" ");
00170                         valueString.append(valueString2);
00171                 }
00172                 m_pCurrentMaterial->setName(valueString);
00173                 //qDebug() << "Material name is : " << valueString;
00174                 result= true;
00175         }
00176         else
00177         {
00178                 m_LoadStatus= "GLC_ObjMtlLoader::extractMaterialName : something is wrong!!";
00179                 result= false;
00180         }
00181         return result;
00182 }
00183 // Extract the texture file name
00184 void GLC_ObjMtlLoader::extractTextureFileName(QString &ligne)
00185 {
00186         QTextStream stream(&ligne);
00187         QString valueString;
00188         QString header;
00189         if ((stream >> header >> valueString).status() == QTextStream::Ok)
00190         {
00191                 // Retrieve the .obj file path
00192                 QFileInfo fileInfo(m_FileName);
00193 
00194                 QString textureFileName(fileInfo.absolutePath() + QDir::separator());
00195                 // concatenate File Path with texture filename
00196                 textureFileName.append(getTextureName(stream, valueString));
00197 
00198                 QFile textureFile(textureFileName);
00199 
00200                 if (!textureFile.open(QIODevice::ReadOnly))
00201                 {
00202                         QStringList stringList(m_FileName);
00203                         stringList.append("Open File : " + textureFileName + " failed");
00204                         GLC_ErrorLog::addError(stringList);
00205                 }
00206                 else if ((textureFileName.right(3).contains("TGA", Qt::CaseInsensitive)))
00207                 {
00208                         QStringList stringList(m_FileName);
00209                         stringList.append("Image : " + textureFileName + " not suported");
00210                         GLC_ErrorLog::addError(stringList);
00211                 }
00212                 else
00213                 {
00214                         m_ListOfAttachedFileName << textureFileName;
00215                         // Create the texture and assign it to current material
00216                         GLC_Texture *pTexture = new GLC_Texture(textureFile);
00217                         m_pCurrentMaterial->setTexture(pTexture);
00218                         //qDebug() << "Texture File is : " << valueString;
00219                 }
00220                 textureFile.close();
00221         }
00222 }
00223 
00224 // Extract RGB value
00225 bool GLC_ObjMtlLoader::extractRGBValue(QString &ligne)
00226 {
00227         bool result= false;
00228         QTextStream stream(&ligne);
00229         QString header;
00230         QString rColor, gColor, bColor;
00231         QColor color(Qt::white);
00232 
00233         if ((stream >> header >> rColor >> gColor >> bColor).status() == QTextStream::Ok)
00234         {
00235                 bool okr, okg, okb;
00236                 color.setRedF(rColor.toDouble(&okr));
00237                 color.setGreenF(gColor.toDouble(&okg));
00238                 color.setBlueF(bColor.toDouble(&okb));
00239                 if (!(okr && okg && okb))
00240                 {
00241                         m_LoadStatus= "GLC_ObjMtlLoader::ExtractRGBValue : Wrong format of rgb color value!!";
00242                         qDebug() << m_LoadStatus;
00243                         result= false;
00244                 }
00245                 else
00246                 {
00247                         color.setAlphaF(1.0);
00248                         if (header == "Ka") // Ambiant Color
00249                         {
00250                                 m_pCurrentMaterial->setAmbientColor(color);
00251                                 //qDebug() << "Ambiant Color : " <<  color.redF() << " " << color.greenF() << " " << color.blueF();
00252                                 result= true;
00253                         }
00254 
00255                         else if (header == "Kd") // Diffuse Color
00256                         {
00257                                 m_pCurrentMaterial->setDiffuseColor(color);
00258                                 //qDebug() << "Diffuse Color : " <<  color.redF() << " " << color.greenF() << " " << color.blueF();
00259                                 result= true;
00260                         }
00261 
00262                         else if (header == "Ks") // Specular Color
00263                         {
00264                                 m_pCurrentMaterial->setSpecularColor(color);
00265                                 //qDebug() << "Specular Color : " <<  color.redF() << " " << color.greenF() << " " << color.blueF();
00266                                 result= true;
00267                         }
00268 
00269                         else
00270                         {
00271                                 m_LoadStatus= "GLC_ObjMtlLoader::ExtractRGBValue : something is wrong!!";
00272                                 result= false;
00273                         }
00274                 }
00275 
00276         }else
00277         {
00278                 m_LoadStatus= "GLC_ObjMtlLoader::ExtractRGBValue : something is wrong!!";
00279                 qDebug() << m_LoadStatus;
00280                 result= false;
00281         }
00282 
00283         return result;
00284 
00285 }
00286 
00287 // Extract One value
00288 bool GLC_ObjMtlLoader::extractOneValue(QString &ligne)
00289 {
00290         QTextStream stream(&ligne);
00291         QString valueString;
00292         QString header;
00293         GLfloat value;
00294 
00295         if ((stream >> header >> valueString).status() == QTextStream::Ok)
00296         {
00297                 if (header == "Ns") // Ambient color
00298                 {
00299                         bool ok;
00300                         value= valueString.toFloat(&ok);
00301                         if (!ok)
00302                         {
00303                                 m_LoadStatus= "GLC_ObjMtlLoader::ExtractOneValue : Wrong format of Shiness !";
00304                                 qDebug() << m_LoadStatus;
00305                                 return false;
00306                         }
00307                         m_pCurrentMaterial->setShininess(value);
00308                         return true;
00309                 }
00310                 else if (header == "d") // Transparancy
00311                 {
00312                         bool ok;
00313                         value= valueString.toFloat(&ok);
00314                         if (!ok)
00315                         {
00316                                 m_LoadStatus= "GLC_ObjMtlLoader::ExtractOneValue : Wrong format Transparency!";
00317                                 qDebug() << m_LoadStatus;
00318                                 return false;
00319                         }
00320                         m_pCurrentMaterial->setOpacity(static_cast<qreal>(value));
00321                         return true;
00322                 }
00323 
00324                 else
00325                 {
00326                         m_LoadStatus= "GLC_ObjMtlLoader::ExtractOneValue : Ambient Color not found!!";
00327                         qDebug() << m_LoadStatus;
00328                         return false;
00329                 }
00330         }
00331         else
00332         {
00333                 m_LoadStatus= "GLC_ObjMtlLoader::ExtractOneValue : something is wrong!!";
00334                 qDebug() << m_LoadStatus;
00335                 GLC_FileFormatException fileFormatException(m_LoadStatus, m_FileName, GLC_FileFormatException::WrongFileFormat);
00336                 return false;
00337         }
00338 
00339 }
00340 
00341 // Get texture file name without parameters
00342 QString GLC_ObjMtlLoader::getTextureName(QTextStream &inputStream, const QString &input)
00343 {
00344         QString textureName(input);
00345         int numberOfStringToSkip= 0;
00346         // Check if there is a map parameter and count
00347         if ((input == "-o") || (input == "-s") || (input == "-t"))
00348         {
00349                 numberOfStringToSkip= 3;
00350         }
00351         else if (input == "-mm")
00352         {
00353                 numberOfStringToSkip= 2;
00354         }
00355         else if ((input == "-blendu") || (input == "-blendv") || (input == "-cc")
00356                         || (input == "-clamp") || (input == "-texres"))
00357         {
00358                 numberOfStringToSkip= 1;
00359         }
00360 
00361         if (numberOfStringToSkip != 0)
00362         {
00363                 // Skip unread map parameters
00364                 for (int i= 0; i < numberOfStringToSkip; ++i)
00365                 {
00366                         inputStream >> textureName;
00367                 }
00368 
00369                 if ((inputStream >> textureName).status() == QTextStream::Ok)
00370                 {
00371                         textureName= getTextureName(inputStream, textureName);
00372                 }
00373                 else
00374                 {
00375                         m_LoadStatus== "GLC_ObjToMesh2::extractString : Error occur when trying to decode map option";
00376                         GLC_FileFormatException fileFormatException(m_LoadStatus, m_FileName, GLC_FileFormatException::WrongFileFormat);
00377                         throw(fileFormatException);
00378                 }
00379         }
00380         return textureName;
00381 }
00382 // Process Maya specific obj
00383 void GLC_ObjMtlLoader::processMayaSpecific()
00384 {
00385         // Test if the current material have a texture
00386         if (m_pCurrentMaterial->hasTexture())
00387         {
00388                 // Test if the diffuse color of material is black
00389                 if (m_pCurrentMaterial->diffuseColor() == Qt::black)
00390                 {
00391                         // Change the material's diffuse color in order to see the texture
00392                         m_pCurrentMaterial->setDiffuseColor(Qt::lightGray);
00393                 }
00394         }
00395 }

SourceForge.net Logo

©2005-2011 Laurent Ribon