glc_objtoworld.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 
00028 #include "glc_objtoworld.h"
00029 #include "../sceneGraph/glc_world.h"
00030 #include "glc_objmtlloader.h"
00031 #include "../glc_fileformatexception.h"
00032 #include "../maths/glc_geomtools.h"
00033 #include "../sceneGraph/glc_structreference.h"
00034 #include "../sceneGraph/glc_structinstance.h"
00035 #include "../sceneGraph/glc_structoccurence.h"
00036 #include <QTextStream>
00037 #include <QFileInfo>
00038 #include <QGLContext>
00039 
00041 // Constructor
00043 GLC_ObjToWorld::GLC_ObjToWorld()
00044 : m_pWorld(NULL)
00045 , m_FileName()
00046 , m_pMtlLoader(NULL)
00047 , m_CurrentLineNumber(0)
00048 , m_pCurrentObjMesh(NULL)
00049 , m_FaceType(notSet)
00050 , m_CurrentMeshMaterials()
00051 , m_CurrentMaterialName("GLC_Default")
00052 , m_ListOfAttachedFileName()
00053 , m_Positions()
00054 , m_Normals()
00055 , m_Texels()
00056 {
00057 }
00058 
00059 GLC_ObjToWorld::~GLC_ObjToWorld()
00060 {
00061         clear();
00062 }
00063 
00065 // Set Functions
00067 
00068 // Create an GLC_World from an input OBJ File
00069 GLC_World* GLC_ObjToWorld::CreateWorldFromObj(QFile &file)
00070 {
00071         m_ListOfAttachedFileName.clear();
00072         m_FileName= file.fileName();
00074         // Test if the file exist and can be opened
00076         if (!file.open(QIODevice::ReadOnly))
00077         {
00078                 QString message(QString("GLC_ObjToWorld::CreateWorldFromObj File ") + m_FileName + QString(" doesn't exist"));
00079                 //qDebug() << message;
00080                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotFound);
00081                 throw(fileFormatException);
00082         }
00083 
00085         // Init member
00087         m_pWorld= new GLC_World;
00088 
00089         // Create Working variables
00090         int currentQuantumValue= 0;
00091         int previousQuantumValue= 0;
00092         int numberOfLine= 0;
00093 
00094         // Create the input file stream
00095         QTextStream objStream(&file);
00096 
00097         // QString buffer
00098         QString lineBuff;
00099 
00100         QString mtlLibLine;
00101 
00103         // Searching mtllib attribute
00105         while (!objStream.atEnd() && !lineBuff.contains("mtllib"))
00106         {
00107                 ++numberOfLine;
00108                 lineBuff= objStream.readLine();
00109                 if (lineBuff.contains("mtllib")) mtlLibLine= lineBuff;
00110         }
00111 
00113         // Count the number of lines of the OBJ file
00115         while (!objStream.atEnd())
00116         {
00117                 ++numberOfLine;
00118                 objStream.readLine();
00119         }
00120 
00122         // Reset the stream
00124         objStream.resetStatus();
00125         objStream.seek(0);
00126 
00128         // if mtl file found, load it
00130         QString mtlLibFileName(getMtlLibFileName(mtlLibLine));
00131         if (!mtlLibFileName.isEmpty())
00132         {
00133                 m_pMtlLoader= new GLC_ObjMtlLoader(mtlLibFileName);
00134                 if (!m_pMtlLoader->loadMaterials())
00135                 {
00136                         delete m_pMtlLoader;
00137                         m_pMtlLoader= NULL;
00138                         if (!mtlLibLine.isEmpty())
00139                         {
00140                                 QStringList stringList(m_FileName);
00141                                 stringList.append("Open Material File : " + mtlLibFileName + " failed");
00142                                 GLC_ErrorLog::addError(stringList);
00143                         }
00144                 }
00145                 else
00146                 {
00147                         // Update Attached file name list
00148                         m_ListOfAttachedFileName << mtlLibFileName;
00149                         m_ListOfAttachedFileName << m_pMtlLoader->listOfAttachedFileName();
00150                 }
00151         }
00152         else
00153         {
00154                 //qDebug() << "GLC_ObjToWorld::CreateWorldFromObj: mtl file not found";
00155         }
00156 
00158         // Read Buffer and create the world
00160         emit currentQuantum(currentQuantumValue);
00161         m_CurrentLineNumber= 0;
00162         while (!objStream.atEnd())
00163         {
00164                 ++m_CurrentLineNumber;
00165                 lineBuff= objStream.readLine();
00166 
00167                 mergeLines(&lineBuff, &objStream);
00168 
00169                 scanLigne(lineBuff);
00170                 currentQuantumValue = static_cast<int>((static_cast<double>(m_CurrentLineNumber) / numberOfLine) * 100);
00171                 if (currentQuantumValue > previousQuantumValue)
00172                 {
00173                         emit currentQuantum(currentQuantumValue);
00174                 }
00175                 previousQuantumValue= currentQuantumValue;
00176 
00177         }
00178         file.close();
00179 
00180         addCurrentObjMeshToWorld();
00181 
00183         if (m_pWorld->rootOccurence()->childCount() == 0)
00184         {
00185                 QString message= "GLC_ObjToWorld::CreateWorldFromObj " + m_FileName + " No mesh found!";
00186                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::NoMeshFound);
00187                 clear();
00188                 throw(fileFormatException);
00189         }
00190         return m_pWorld;
00191 
00192 }
00193 
00195 // Private services functions
00197 
00198 // Return the name of the mtl file
00199 QString GLC_ObjToWorld::getMtlLibFileName(QString line)
00200 {
00201         // Search mtl file with the same name than the OBJ file Name
00202         QString mtlFileName(m_FileName);
00203         mtlFileName.replace(m_FileName.size() - 3, 3, "mtl");
00204         QFile mtlFile(mtlFileName);
00205         if (!mtlFile.exists())// mtl file with same name not found
00206         {
00207                 QTextStream stream(&line);
00208                 QString header;
00209                 if ((stream >> header >> mtlFileName).status() == QTextStream::Ok)
00210                 {
00211                         // If There is spaces in the string to extracts
00212                         QString valueString2;
00213                         while ((stream >> valueString2).status() == QTextStream::Ok)
00214                         {
00215                                 mtlFileName.append(" ");
00216                                 mtlFileName.append(valueString2);
00217                         }
00218                         QFileInfo fileInfo(m_FileName);
00219                         mtlFileName= fileInfo.absolutePath() + QDir::separator() + mtlFileName;
00220                 }
00221                 else
00222                 {
00223                         // There is no mtl file to load
00224                         mtlFileName.clear();
00225                 }
00226         }
00227         return mtlFileName;
00228 }
00229 
00230 // Scan a line previously extracted from OBJ file
00231 void GLC_ObjToWorld::scanLigne(QString &line)
00232 {
00233         line= line.trimmed();
00234         // Search Vertexs vectors
00235         if (line.startsWith("v ")|| line.startsWith(QString("v") + QString(QChar(9))))
00236         {
00237                 line.remove(0,2); // Remove first 2 char
00238                 m_Positions.append(extract3dVect(line));
00239                 m_FaceType = notSet;
00240         }
00241 
00242         // Search texture coordinate vectors
00243         else if (line.startsWith("vt ")|| line.startsWith(QString("vt") + QString(QChar(9))))
00244         {
00245                 line.remove(0,3); // Remove first 3 char
00246                 m_Texels.append(extract2dVect(line));
00247                 m_FaceType = notSet;
00248         }
00249 
00250         // Search normals vectors
00251         else if (line.startsWith("vn ") || line.startsWith(QString("vn") + QString(QChar(9))))
00252         {
00253                 line.remove(0,3); // Remove first 3 char
00254                 m_Normals.append(extract3dVect(line));
00255                 m_FaceType = notSet;
00256         }
00257 
00258         // Search faces to update index
00259         else if (line.startsWith("f ") || line.startsWith(QString("f") + QString(QChar(9))))
00260         {
00261                 // If there is no group or object in the OBJ file
00262                 if (NULL == m_pCurrentObjMesh)
00263                         {
00264                                 changeGroup("GLC_Default");
00265                                 //qDebug() << "Default group " << line;
00266                         }
00267                 line.remove(0,2); // Remove first 2 char
00268                 extractFaceIndex(line);
00269         }
00270 
00271         // Search Material
00272         else if (line.startsWith("usemtl ") || line.startsWith(QString("usemtl") + QString(QChar(9))))
00273         {
00274                 line.remove(0,7); // Remove first 7 char
00275                 setCurrentMaterial(line);
00276                 m_FaceType = notSet;
00277         }
00278 
00279         // Search Group
00280         else if (line.startsWith("g ") || line.startsWith("o ") || line.startsWith(QString("g") + QString(QChar(9)))
00281                         || line.startsWith(QString("o") + QString(QChar(9))))
00282         {
00283                 m_FaceType = notSet;
00284                 line.remove(0,2); // Remove first 2 char
00285                 changeGroup(line);
00286         }
00287 
00288 }
00289 // Change current group
00290 void GLC_ObjToWorld::changeGroup(QString line)
00291 {
00292         //qDebug() << "GLC_ObjToWorld::changeGroup at Line :" << line;
00294         // Parse the line containing the group name
00296         QTextStream stream(&line);
00297         QString groupName;
00298         if ((stream >> groupName).status() == QTextStream::Ok)
00299         {
00300                 // If There is an space in the string to extracts
00301                 QString valueString2;
00302                 while ((stream >> valueString2).status() == QTextStream::Ok)
00303                 {
00304                         groupName.append(" ");
00305                         groupName.append(valueString2);
00306                 }
00308                 // If the groupName == "default" nothing to do
00310                 if("default" != groupName)
00311                 {
00312                         addCurrentObjMeshToWorld();
00313                         m_pCurrentObjMesh= new CurrentObjMesh(m_CurrentMaterialName);
00314                         m_pCurrentObjMesh->m_pMesh->setName(groupName);
00315 
00316                 }
00317         }
00318         else
00319         {
00320                 QString message= "GLC_ObjToWorld::changeGroup " + m_FileName + " something is wrong!!";
00321                 message.append("\nAt line : ");
00322                 message.append(QString::number(m_CurrentLineNumber));
00323                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00324                 clear();
00325                 throw(fileFormatException);
00326         }
00327 
00328 }
00329 
00330 // Extract a Vector from a string
00331 QList<float> GLC_ObjToWorld::extract3dVect(QString &line)
00332 {
00333         float x=0.0f;
00334         float y=0.0f;
00335         float z=0.0f;
00336 
00337         QList<float> vectResult;
00338         QTextStream stringVecteur(&line);
00339 
00340         QString xString, yString, zString;
00341 
00342         if (((stringVecteur >> xString >> yString >> zString).status() == QTextStream::Ok))
00343         {
00344                 bool xOk, yOk, zOk;
00345                 x= xString.toFloat(&xOk);
00346                 y= yString.toFloat(&yOk);
00347                 z= zString.toFloat(&zOk);
00348                 if (!(xOk && yOk && zOk))
00349                 {
00350                         QString message= "GLC_ObjToWorld::extract3dVect " + m_FileName + " failed to convert vector component to float";
00351                         message.append("\nAt ligne : ");
00352                         message.append(QString::number(m_CurrentLineNumber));
00353                         QStringList stringList(m_FileName);
00354                         stringList.append(message);
00355                         GLC_ErrorLog::addError(stringList);
00356 
00357                         //GLC_FileFormatException fileFormatException(message, m_FileName);
00358                         //clear();
00359                         //throw(fileFormatException);
00360                 }
00361                 else
00362                 {
00363                         vectResult << x << y << z;
00364                 }
00365         }
00366 
00367         return vectResult;
00368 
00369 }
00370 
00371 // Extract a Vector from a string
00372 QList<float> GLC_ObjToWorld::extract2dVect(QString &line)
00373 {
00374         float x=0.0f;
00375         float y=0.0f;
00376         QList<float> vectResult;
00377         QTextStream stringVecteur(&line);
00378 
00379         QString xString, yString;
00380 
00381         if (((stringVecteur >> xString >> yString).status() == QTextStream::Ok))
00382         {
00383                 bool xOk, yOk;
00384                 x= xString.toFloat(&xOk);
00385                 y= yString.toFloat(&yOk);
00386                 if (!(xOk && yOk))
00387                 {
00388                         QString message= "GLC_ObjToWorld::extract2dVect " + m_FileName + " failed to convert vector component to double";
00389                         message.append("\nAt ligne : ");
00390                         message.append(QString::number(m_CurrentLineNumber));
00391                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00392                         clear();
00393                         throw(fileFormatException);
00394                 }
00395                 vectResult << x << y;
00396         }
00397 
00398         return vectResult;
00399 }
00400 
00401 // Extract a face from a string
00402 void GLC_ObjToWorld::extractFaceIndex(QString &line)
00403 {
00404         QString buff;
00405 
00406         int coordinateIndex;
00407         int normalIndex;
00408         int textureCoordinateIndex;
00409 
00410         QList<GLuint> currentFaceIndex;
00412         // Parse the line containing face index
00414         QTextStream streamFace(&line);
00415         while ((!streamFace.atEnd()))
00416         {
00417                 streamFace >> buff;
00418                 extractVertexIndex(buff, coordinateIndex, normalIndex, textureCoordinateIndex);
00419 
00420                 ObjVertice currentVertice(coordinateIndex, normalIndex, textureCoordinateIndex);
00421                 if (m_pCurrentObjMesh->m_ObjVerticeIndexMap.contains(currentVertice))
00422                 {
00423                         currentFaceIndex.append(m_pCurrentObjMesh->m_ObjVerticeIndexMap.value(currentVertice));
00424                 }
00425                 else
00426                 {
00427                         // Add Vertex to the mesh bulk data
00428                         m_pCurrentObjMesh->m_Positions.append(m_Positions.value(coordinateIndex * 3));
00429                         m_pCurrentObjMesh->m_Positions.append(m_Positions.value(coordinateIndex * 3 + 1));
00430                         m_pCurrentObjMesh->m_Positions.append(m_Positions.value(coordinateIndex * 3 + 2));
00431                         if (-1 != normalIndex)
00432                         {
00433                                 // Add Normal to the mesh bulk data
00434                                 m_pCurrentObjMesh->m_Normals.append(m_Normals.value(normalIndex * 3));
00435                                 m_pCurrentObjMesh->m_Normals.append(m_Normals.value(normalIndex * 3 + 1));
00436                                 m_pCurrentObjMesh->m_Normals.append(m_Normals.value(normalIndex * 3 + 2));
00437                         }
00438                         else
00439                         {
00440                                 // Add Null Normal to the mesh bulk data
00441                                 m_pCurrentObjMesh->m_Normals.append(0.0f);
00442                                 m_pCurrentObjMesh->m_Normals.append(0.0f);
00443                                 m_pCurrentObjMesh->m_Normals.append(0.0f);
00444                         }
00445                         if (-1 != textureCoordinateIndex)
00446                         {
00447                                 // Add texture coordinate to the mesh bulk data
00448                                 m_pCurrentObjMesh->m_Texels.append(m_Texels.value(textureCoordinateIndex * 2));
00449                                 m_pCurrentObjMesh->m_Texels.append(m_Texels.value(textureCoordinateIndex * 2 + 1));
00450                         }
00451                         else if (!m_pCurrentObjMesh->m_Texels.isEmpty())
00452                         {
00453                                 // Add epmty texture coordinate
00454                                 m_pCurrentObjMesh->m_Texels.append(0.0f);
00455                                 m_pCurrentObjMesh->m_Texels.append(0.0f);
00456                         }
00457                         // Add the index to current face index
00458                         currentFaceIndex.append(m_pCurrentObjMesh->m_NextFreeIndex);
00459                         // Add ObjVertice to ObjVertice Map
00460                         m_pCurrentObjMesh->m_ObjVerticeIndexMap.insert(currentVertice, m_pCurrentObjMesh->m_NextFreeIndex);
00461                         // Increment next free index
00462                         ++(m_pCurrentObjMesh->m_NextFreeIndex);
00463                 }
00464 
00465         }
00467         // Check the number of face's vertex
00469         const int size= currentFaceIndex.size();
00470         if (size < 3)
00471         {
00472                 QStringList stringList(m_FileName);
00473                 stringList.append("GLC_ObjToWorld::extractFaceIndex Face with less than 3 vertex found");
00474                 GLC_ErrorLog::addError(stringList);
00475                 return;
00476         }
00478         // Add the face to the current mesh
00480         if ((m_FaceType == coordinateAndNormal) || (m_FaceType == coordinateAndTextureAndNormal))
00481         {
00482                 if (size > 3)
00483                 {
00484                         glc::triangulatePolygon(&currentFaceIndex, m_pCurrentObjMesh->m_Positions);
00485                 }
00486                 m_pCurrentObjMesh->m_Index.append(currentFaceIndex);
00487         }
00488         else if (m_FaceType != notSet)
00489         {
00490                 if (size > 3)
00491                 {
00492                         glc::triangulatePolygon(&currentFaceIndex, m_pCurrentObjMesh->m_Positions);
00493                 }
00494                 // Comput the face normal
00495                 if (currentFaceIndex.size() < 3) return;
00496                 GLC_Vector3df normal= computeNormal(currentFaceIndex.at(0), currentFaceIndex.at(1), currentFaceIndex.at(2));
00497 
00498                 // Add Face normal to bulk data
00499                 QSet<GLuint> indexSet= currentFaceIndex.toSet();
00500                 QSet<GLuint>::iterator iIndexSet= indexSet.begin();
00501                 while (indexSet.constEnd() != iIndexSet)
00502                 {
00503                         m_pCurrentObjMesh->m_Normals[*iIndexSet * 3]= normal.x();
00504                         m_pCurrentObjMesh->m_Normals[*iIndexSet * 3 + 1]= normal.y();
00505                         m_pCurrentObjMesh->m_Normals[*iIndexSet * 3 + 2]= normal.z();
00506 
00507                         ++iIndexSet;
00508                 }
00509 
00510                 m_pCurrentObjMesh->m_Index.append(currentFaceIndex);
00511 
00512         }
00513         else
00514         {
00515                 QString message= "GLC_ObjToWorld::extractFaceIndex " + m_FileName + " unknow face type";
00516                 message.append("\nAt line : ");
00517                 message.append(QString::number(m_CurrentLineNumber));
00518                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00519                 clear();
00520                 throw(fileFormatException);
00521         }
00522 }
00524 void GLC_ObjToWorld::setCurrentMaterial(QString &line)
00525 {
00526         QTextStream streamString(&line);
00527         QString materialName;
00528 
00529         if (!((streamString >> materialName).status() == QTextStream::Ok))
00530         {
00531                 QString message= "GLC_ObjToWorld::SetCurrentMaterial " + m_FileName + " : failed to extract materialName";
00532                 message.append("\nAt line : ");
00533                 message.append(QString::number(m_CurrentLineNumber));
00534                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00535                 clear();
00536                 throw(fileFormatException);
00537         }
00539         // Check if the material is already loaded from the current mesh
00541         if ((NULL != m_pMtlLoader) && m_pMtlLoader->contains(materialName))
00542         {
00543                 if (NULL == m_pCurrentObjMesh)
00544                 {
00545                         changeGroup("GLC_Default");
00546                 }
00547                 Q_ASSERT(NULL != m_pCurrentObjMesh->m_pLastOffsetSize);
00548 
00549                 if (m_pCurrentObjMesh->m_Index.size() != m_pCurrentObjMesh->m_pLastOffsetSize->m_Offset)
00550                 {
00551                         // Update last material offsetSize
00552                         m_pCurrentObjMesh->m_pLastOffsetSize->m_size= m_pCurrentObjMesh->m_Index.size() - m_pCurrentObjMesh->m_pLastOffsetSize->m_Offset;
00553                 }
00554                 else
00555                 {
00556                         QHash<QString, MatOffsetSize*>::iterator iMat= m_pCurrentObjMesh->m_Materials.begin();
00557                         while (m_pCurrentObjMesh->m_Materials.constEnd() != iMat)
00558                         {
00559                                 if (iMat.value() == m_pCurrentObjMesh->m_pLastOffsetSize)
00560                                 {
00561                                         iMat= m_pCurrentObjMesh->m_Materials.erase(iMat);
00562                                 }
00563                                 else
00564                                 {
00565                                         ++iMat;
00566                                 }
00567                         }
00568                 }
00569                 // Create this material offsetSize
00570                 MatOffsetSize* pMatOffsetSize= new MatOffsetSize();
00571                 pMatOffsetSize->m_Offset= m_pCurrentObjMesh->m_Index.size();
00572                 // Update current Obj mesh
00573                 m_pCurrentObjMesh->m_pLastOffsetSize= pMatOffsetSize;
00574                 m_pCurrentObjMesh->m_Materials.insertMulti(materialName, pMatOffsetSize);
00575                 // Update current material name
00576                 m_CurrentMaterialName= materialName;
00577         }
00578 
00579 }
00580 // Extract a vertex from a string
00581 void GLC_ObjToWorld::extractVertexIndex(QString line, int &Coordinate, int &Normal, int &TextureCoordinate)
00582 {
00583         if (m_FaceType == notSet)
00584         {
00585                 setObjType(line);
00586         }
00587 
00588         if (m_FaceType == coordinateAndTextureAndNormal)
00589         {
00590                 // Replace "/" with " "
00591                 line.replace('/', ' ');
00592                 QTextStream streamVertex(&line);
00593                 QString coordinateString, textureCoordinateString, normalString;
00594                 if ((streamVertex >> coordinateString >> textureCoordinateString >> normalString).status() == QTextStream::Ok)
00595                 {
00596                         bool coordinateOk, textureCoordinateOk, normalOk;
00597                         Coordinate= coordinateString.toInt(&coordinateOk);
00598                         --Coordinate;
00599                         TextureCoordinate= textureCoordinateString.toInt(&textureCoordinateOk);
00600                         --TextureCoordinate;
00601                         Normal= normalString.toInt(&normalOk);
00602                         --Normal;
00603                         if (!(coordinateOk && textureCoordinateOk && normalOk))
00604                         {
00605                                 QString message= "GLC_ObjToWorld::extractVertexIndex " + m_FileName + " failed to convert String to int";
00606                                 message.append("\nAt line : ");
00607                                 message.append(QString::number(m_CurrentLineNumber));
00608                                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00609                                 clear();
00610                                 throw(fileFormatException);
00611                         }
00612                 }
00613                 else
00614                 {
00615                         QString message= "GLC_ObjToWorld::extractVertexIndex Obj file " + m_FileName + " type is not supported";
00616                         message.append("\nAt line : ");
00617                         message.append(QString::number(m_CurrentLineNumber));
00618                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00619                         clear();
00620                         throw(fileFormatException);
00621                 }
00622 
00623         }
00624         else if (m_FaceType == coordinateAndTexture)
00625         {
00626                 // Replace "/" with " "
00627                 line.replace('/', ' ');
00628                 QTextStream streamVertex(&line);
00629                 QString coordinateString, textureCoordinateString;
00630                 if ((streamVertex >> coordinateString >> textureCoordinateString).status() == QTextStream::Ok)
00631                 {
00632                         bool coordinateOk, textureCoordinateOk;
00633                         Coordinate= coordinateString.toInt(&coordinateOk);
00634                         --Coordinate;
00635                         TextureCoordinate= textureCoordinateString.toInt(&textureCoordinateOk);
00636                         --TextureCoordinate;
00637                         Normal= -1;
00638                         if (!(coordinateOk && textureCoordinateOk))
00639                         {
00640                                 QString message= "GLC_ObjToWorld::extractVertexIndex " + m_FileName +  "failed to convert String to int";
00641                                 message.append("\nAt line : ");
00642                                 message.append(QString::number(m_CurrentLineNumber));
00643                                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00644                                 clear();
00645                                 throw(fileFormatException);
00646                         }
00647                 }
00648                 else
00649                 {
00650                         QString message= "GLC_ObjToWorld::extractVertexIndex " + m_FileName + " this Obj file type is not supported";
00651                         message.append("\nAt line : ");
00652                         message.append(QString::number(m_CurrentLineNumber));
00653                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00654                         clear();
00655                         throw(fileFormatException);
00656                 }
00657         }
00658         else if (m_FaceType == coordinateAndNormal)
00659         {
00660                 // Replace "/" with " "
00661                 line.replace('/', ' ');
00662                 QTextStream streamVertex(&line);
00663                 QString coordinateString, normalString;
00664                 if ((streamVertex >> coordinateString >> normalString).status() == QTextStream::Ok)
00665                 {
00666                         bool coordinateOk, normalOk;
00667                         Coordinate= coordinateString.toInt(&coordinateOk);
00668                         --Coordinate;
00669                         TextureCoordinate= -1;
00670                         Normal= normalString.toInt(&normalOk);
00671                         --Normal;
00672                         if (!(coordinateOk && normalOk))
00673                         {
00674                                 QString message= "GLC_ObjToWorld::extractVertexIndex " + m_FileName + " failed to convert String to int";
00675                                 message.append("\nAt line : ");
00676                                 message.append(QString::number(m_CurrentLineNumber));
00677                                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00678                                 clear();
00679                                 throw(fileFormatException);
00680                         }
00681                 }
00682                 else
00683                 {
00684                         QString message= "GLC_ObjToWorld::extractVertexIndex " + m_FileName + " this Obj file type is not supported";
00685                         message.append("\nAt line : ");
00686                         message.append(QString::number(m_CurrentLineNumber));
00687                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00688                         clear();
00689                         throw(fileFormatException);
00690                 }
00691         }
00692         else if (m_FaceType == coordinate)
00693         {
00694                 QTextStream streamVertex(&line);
00695                 QString coordinateString;
00696                 if ((streamVertex >> coordinateString).status() == QTextStream::Ok)
00697                 {
00698                         bool coordinateOk;
00699                         Coordinate= coordinateString.toInt(&coordinateOk);
00700                         --Coordinate;
00701                         TextureCoordinate= -1;
00702                         Normal= -1;
00703                         if (!coordinateOk)
00704                         {
00705                                 QString message= "GLC_ObjToWorld::extractVertexIndex "  + m_FileName + " failed to convert String to int";
00706                                 message.append("\nAt line : ");
00707                                 message.append(QString::number(m_CurrentLineNumber));
00708                                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00709                                 clear();
00710                                 throw(fileFormatException);
00711                         }
00712                 }
00713                 else
00714                 {
00715                         QString message= "GLC_ObjToWorld::extractVertexIndex Obj " + m_FileName + " file type is not supported";
00716                         message.append("\nAt line : ");
00717                         message.append(QString::number(m_CurrentLineNumber));
00718                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00719                         clear();
00720                         throw(fileFormatException);
00721                 }
00722         }
00723         else
00724         {
00725                 QString message= "GLC_ObjToWorld::extractVertexIndex OBJ file " + m_FileName + " not reconize";
00726                 message.append("\nAt line : ");
00727                 message.append(QString::number(m_CurrentLineNumber));
00728                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00729                 clear();
00730                 throw(fileFormatException);
00731         }
00732 }
00733 
00734 // set the OBJ File type
00735 void GLC_ObjToWorld::setObjType(QString& ligne)
00736 {
00737         const QRegExp coordinateOnlyRegExp("^\\d{1,}$"); // ex. 10
00738         const QRegExp coordinateTextureNormalRegExp("^\\d{1,}/\\d{1,}/\\d{1,}$"); // ex. 10/30/54
00739         const QRegExp coordinateNormalRegExp("^\\d{1,}//\\d{1,}$"); // ex. 10//54
00740         const QRegExp coordinateTextureRegExp("^\\d{1,}/\\d{1,}$"); // ex. 10/56
00741 
00742         if (coordinateTextureNormalRegExp.exactMatch(ligne))
00743         {
00744                 m_FaceType= coordinateAndTextureAndNormal;
00745         }
00746         else if (coordinateTextureRegExp.exactMatch(ligne))
00747         {
00748                 m_FaceType= coordinateAndTexture;
00749         }
00750         else if (coordinateNormalRegExp.exactMatch(ligne))
00751         {
00752                 m_FaceType= coordinateAndNormal;
00753         }
00754         else if (coordinateOnlyRegExp.exactMatch(ligne))
00755         {
00756                 m_FaceType= coordinate;
00757         }
00758         else
00759         {
00760                 QString message= "GLC_ObjToWorld::setObjType OBJ file " + m_FileName + " not reconize";
00761                 message.append("\nAt line : ");
00762                 message.append(QString::number(m_CurrentLineNumber));
00763                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00764                 clear();
00765                 throw(fileFormatException);
00766         }
00767 }
00768 
00769 // compute face normal
00770 GLC_Vector3df GLC_ObjToWorld::computeNormal(GLuint index1, GLuint index2, GLuint index3)
00771 {
00772         double xn, yn, zn;
00773 
00774         // Vertex 1
00775         xn= m_pCurrentObjMesh->m_Positions.at(index1 * 3);
00776         yn= m_pCurrentObjMesh->m_Positions.at(index1 * 3 + 1);
00777         zn= m_pCurrentObjMesh->m_Positions.at(index1 * 3 + 2);
00778         const GLC_Vector3d vect1(xn, yn, zn);
00779 
00780         // Vertex 2
00781         xn= m_pCurrentObjMesh->m_Positions.at(index2 * 3);
00782         yn= m_pCurrentObjMesh->m_Positions.at(index2 * 3 + 1);
00783         zn= m_pCurrentObjMesh->m_Positions.at(index2 * 3 + 2);
00784         const GLC_Vector3d vect2(xn, yn, zn);
00785 
00786         // Vertex 3
00787         xn= m_pCurrentObjMesh->m_Positions.at(index3 * 3);
00788         yn= m_pCurrentObjMesh->m_Positions.at(index3 * 3 + 1);
00789         zn= m_pCurrentObjMesh->m_Positions.at(index3 * 3 + 2);
00790         const GLC_Vector3d vect3(xn, yn, zn);
00791 
00792         const GLC_Vector3d edge1(vect3 - vect2);
00793         const GLC_Vector3d edge2(vect1 - vect2);
00794 
00795         GLC_Vector3d normal(edge1 ^ edge2);
00796         normal.normalize();
00797 
00798         return normal.toVector3df();
00799 }
00800 
00801 // clear objToWorld allocate memmory
00802 void GLC_ObjToWorld::clear()
00803 {
00804         m_CurrentMeshMaterials.clear();
00805         m_ListOfAttachedFileName.clear();
00806 
00807         if (NULL != m_pMtlLoader)
00808         {
00809                 delete m_pMtlLoader;
00810                 m_pMtlLoader= NULL;
00811         }
00812         if (NULL != m_pCurrentObjMesh)
00813         {
00814                 delete m_pCurrentObjMesh;
00815                 m_pCurrentObjMesh= NULL;
00816         }
00817 
00818 }
00819 // Merge Mutli line in one
00820 void GLC_ObjToWorld::mergeLines(QString* pLineBuff, QTextStream* p0bjStream)
00821 {
00822         if (pLineBuff->endsWith(QChar('\\')))
00823         {
00824                 pLineBuff->replace(QChar('\\'), QChar(' '));
00825                 pLineBuff->append(p0bjStream->readLine());
00826                 ++m_CurrentLineNumber;
00827                 mergeLines(pLineBuff, p0bjStream);
00828         }
00829 }
00830 
00831 // Add the current Obj mesh to the world
00832 void GLC_ObjToWorld::addCurrentObjMeshToWorld()
00833 {
00834         if (NULL != m_pCurrentObjMesh)
00835         {
00836                 if (!m_pCurrentObjMesh->m_Positions.isEmpty())
00837                 {
00838                         m_pCurrentObjMesh->m_pMesh->addVertice(m_pCurrentObjMesh->m_Positions.toVector());
00839                         m_pCurrentObjMesh->m_Positions.clear();
00840                         m_pCurrentObjMesh->m_pMesh->addNormals(m_pCurrentObjMesh->m_Normals.toVector());
00841                         m_pCurrentObjMesh->m_Normals.clear();
00842                         if (!m_pCurrentObjMesh->m_Texels.isEmpty())
00843                         {
00844                                 m_pCurrentObjMesh->m_pMesh->addTexels(m_pCurrentObjMesh->m_Texels.toVector());
00845                                 m_pCurrentObjMesh->m_Texels.clear();
00846                         }
00847                         QHash<QString, MatOffsetSize*>::iterator iMat= m_pCurrentObjMesh->m_Materials.begin();
00848                         while (m_pCurrentObjMesh->m_Materials.constEnd() != iMat)
00849                         {
00850                                 GLC_Material* pCurrentMaterial= NULL;
00851                                 if ((NULL != m_pMtlLoader) && (m_pMtlLoader->contains(iMat.key())))
00852                                 {
00853                                         pCurrentMaterial= m_pMtlLoader->material(iMat.key());
00854                                 }
00855                                 // Create the list of triangles to add to the mesh
00856                                 const int offset= iMat.value()->m_Offset;
00857                                 int size= iMat.value()->m_size;
00858                                 if (0 == size)
00859                                 {
00860                                         size= m_pCurrentObjMesh->m_Index.size() - offset;
00861                                 }
00862                                 //qDebug() << "Offset : " << offset << " size : " << size;
00863                                 QList<GLuint> triangles;
00864                                 for (int i= offset; i < (offset + size); ++i)
00865                                 {
00866                                         triangles.append(m_pCurrentObjMesh->m_Index.at(i));
00867                                 }
00868                                 // Add the list of triangle to the mesh
00869                                 if (!triangles.isEmpty())
00870                                 {
00871                                         m_pCurrentObjMesh->m_pMesh->addTriangles(pCurrentMaterial, triangles);
00872                                 }
00873 
00874                                 ++iMat;
00875                         }
00876                         if (m_pCurrentObjMesh->m_pMesh->faceCount(0) > 0)
00877                         {
00878                                 m_pCurrentObjMesh->m_pMesh->finish();
00879                                 GLC_3DRep* pRep= new GLC_3DRep(m_pCurrentObjMesh->m_pMesh);
00880                                 m_pWorld->rootOccurence()->addChild((new GLC_StructInstance(pRep)));
00881                         }
00882                         else
00883                         {
00884                                 delete m_pCurrentObjMesh->m_pMesh;
00885                         }
00886 
00887                 }
00888                 else
00889                 {
00890                         delete m_pCurrentObjMesh->m_pMesh;
00891                 }
00892 
00893                 delete m_pCurrentObjMesh;
00894                 m_pCurrentObjMesh= NULL;
00895         }
00896 }
00897 
00898 

SourceForge.net Logo

©2005-2011 Laurent Ribon