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

SourceForge.net Logo

©2005 Laurent Ribon