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 Beta 1, packaged on April 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 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 "../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(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 (!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) || (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                 if (NULL == m_pCurrentObjMesh)
00538                 {
00539                         changeGroup("GLC_Default");
00540                 }
00541                 Q_ASSERT(NULL != m_pCurrentObjMesh->m_pLastOffsetSize);
00542 
00543                 if (m_pCurrentObjMesh->m_Index.size() != m_pCurrentObjMesh->m_pLastOffsetSize->m_Offset)
00544                 {
00545                         // Update last material offsetSize
00546                         m_pCurrentObjMesh->m_pLastOffsetSize->m_size= m_pCurrentObjMesh->m_Index.size() - m_pCurrentObjMesh->m_pLastOffsetSize->m_Offset;
00547                 }
00548                 else
00549                 {
00550                         QHash<QString, MatOffsetSize*>::iterator iMat= m_pCurrentObjMesh->m_Materials.begin();
00551                         while (m_pCurrentObjMesh->m_Materials.constEnd() != iMat)
00552                         {
00553                                 if (iMat.value() == m_pCurrentObjMesh->m_pLastOffsetSize)
00554                                 {
00555                                         iMat= m_pCurrentObjMesh->m_Materials.erase(iMat);
00556                                 }
00557                                 else
00558                                 {
00559                                         ++iMat;
00560                                 }
00561                         }
00562                 }
00563                 // Create this material offsetSize
00564                 MatOffsetSize* pMatOffsetSize= new MatOffsetSize();
00565                 pMatOffsetSize->m_Offset= m_pCurrentObjMesh->m_Index.size();
00566                 // Update current Obj mesh
00567                 m_pCurrentObjMesh->m_pLastOffsetSize= pMatOffsetSize;
00568                 m_pCurrentObjMesh->m_Materials.insertMulti(materialName, pMatOffsetSize);
00569                 // Update current material name
00570                 m_CurrentMaterialName= materialName;
00571         }
00572 
00573 }
00574 // Extract a vertex from a string
00575 void GLC_ObjToWorld::extractVertexIndex(QString line, int &Coordinate, int &Normal, int &TextureCoordinate)
00576 {
00577         if (m_FaceType == notSet)
00578         {
00579                 setObjType(line);
00580         }
00581 
00582         if (m_FaceType == coordinateAndTextureAndNormal)
00583         {
00584                 // Replace "/" with " "
00585                 line.replace('/', ' ');
00586                 QTextStream streamVertex(&line);
00587                 QString coordinateString, textureCoordinateString, normalString;
00588                 if ((streamVertex >> coordinateString >> textureCoordinateString >> normalString).status() == QTextStream::Ok)
00589                 {
00590                         bool coordinateOk, textureCoordinateOk, normalOk;
00591                         Coordinate= coordinateString.toInt(&coordinateOk);
00592                         --Coordinate;
00593                         TextureCoordinate= textureCoordinateString.toInt(&textureCoordinateOk);
00594                         --TextureCoordinate;
00595                         Normal= normalString.toInt(&normalOk);
00596                         --Normal;
00597                         if (!(coordinateOk && textureCoordinateOk && normalOk))
00598                         {
00599                                 QString message= "GLC_ObjToWorld::extractVertexIndex failed to convert String to int";
00600                                 message.append("\nAt line : ");
00601                                 message.append(QString::number(m_CurrentLineNumber));
00602                                 qDebug() << message;
00603                                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00604                                 clear();
00605                                 throw(fileFormatException);
00606                         }
00607                 }
00608                 else
00609                 {
00610                         QString message= "GLC_ObjToWorld::extractVertexIndex this Obj file type is not supported";
00611                         message.append("\nAt line : ");
00612                         message.append(QString::number(m_CurrentLineNumber));
00613                         qDebug() << message;
00614                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00615                         clear();
00616                         throw(fileFormatException);
00617                 }
00618 
00619         }
00620         else if (m_FaceType == coordinateAndTexture)
00621         {
00622                 // Replace "/" with " "
00623                 line.replace('/', ' ');
00624                 QTextStream streamVertex(&line);
00625                 QString coordinateString, textureCoordinateString;
00626                 if ((streamVertex >> coordinateString >> textureCoordinateString).status() == QTextStream::Ok)
00627                 {
00628                         bool coordinateOk, textureCoordinateOk;
00629                         Coordinate= coordinateString.toInt(&coordinateOk);
00630                         --Coordinate;
00631                         TextureCoordinate= textureCoordinateString.toInt(&textureCoordinateOk);
00632                         --TextureCoordinate;
00633                         Normal= -1;
00634                         if (!(coordinateOk && textureCoordinateOk))
00635                         {
00636                                 QString message= "GLC_ObjToWorld::extractVertexIndex failed to convert String to int";
00637                                 message.append("\nAt line : ");
00638                                 message.append(QString::number(m_CurrentLineNumber));
00639                                 qDebug() << message;
00640                                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00641                                 clear();
00642                                 throw(fileFormatException);
00643                         }
00644                 }
00645                 else
00646                 {
00647                         QString message= "GLC_ObjToWorld::extractVertexIndex this Obj file type is not supported";
00648                         message.append("\nAt line : ");
00649                         message.append(QString::number(m_CurrentLineNumber));
00650                         qDebug() << message;
00651                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00652                         clear();
00653                         throw(fileFormatException);
00654                 }
00655         }
00656         else if (m_FaceType == coordinateAndNormal)
00657         {
00658                 // Replace "/" with " "
00659                 line.replace('/', ' ');
00660                 QTextStream streamVertex(&line);
00661                 QString coordinateString, normalString;
00662                 if ((streamVertex >> coordinateString >> normalString).status() == QTextStream::Ok)
00663                 {
00664                         bool coordinateOk, normalOk;
00665                         Coordinate= coordinateString.toInt(&coordinateOk);
00666                         --Coordinate;
00667                         TextureCoordinate= -1;
00668                         Normal= normalString.toInt(&normalOk);
00669                         --Normal;
00670                         if (!(coordinateOk && normalOk))
00671                         {
00672                                 QString message= "GLC_ObjToWorld::extractVertexIndex failed to convert String to int";
00673                                 message.append("\nAt line : ");
00674                                 message.append(QString::number(m_CurrentLineNumber));
00675                                 qDebug() << message;
00676                                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00677                                 clear();
00678                                 throw(fileFormatException);
00679                         }
00680                 }
00681                 else
00682                 {
00683                         QString message= "GLC_ObjToWorld::extractVertexIndex this Obj file type is not supported";
00684                         message.append("\nAt line : ");
00685                         message.append(QString::number(m_CurrentLineNumber));
00686                         qDebug() << message;
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 failed to convert String to int";
00706                                 message.append("\nAt line : ");
00707                                 message.append(QString::number(m_CurrentLineNumber));
00708                                 qDebug() << message;
00709                                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00710                                 clear();
00711                                 throw(fileFormatException);
00712                         }
00713                 }
00714                 else
00715                 {
00716                         QString message= "GLC_ObjToWorld::extractVertexIndex this Obj file type is not supported";
00717                         message.append("\nAt line : ");
00718                         message.append(QString::number(m_CurrentLineNumber));
00719                         qDebug() << message;
00720                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00721                         clear();
00722                         throw(fileFormatException);
00723                 }
00724         }
00725         else
00726         {
00727                 QString message= "GLC_ObjToWorld::extractVertexIndex OBJ file not reconize";
00728                 message.append("\nAt line : ");
00729                 message.append(QString::number(m_CurrentLineNumber));
00730                 qDebug() << message;
00731                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00732                 clear();
00733                 throw(fileFormatException);
00734         }
00735 }
00736 
00737 // set the OBJ File type
00738 void GLC_ObjToWorld::setObjType(QString& ligne)
00739 {
00740         const QRegExp coordinateOnlyRegExp("^\\d{1,}$"); // ex. 10
00741         const QRegExp coordinateTextureNormalRegExp("^\\d{1,}/\\d{1,}/\\d{1,}$"); // ex. 10/30/54
00742         const QRegExp coordinateNormalRegExp("^\\d{1,}//\\d{1,}$"); // ex. 10//54
00743         const QRegExp coordinateTextureRegExp("^\\d{1,}/\\d{1,}$"); // ex. 10/56
00744 
00745         if (coordinateTextureNormalRegExp.exactMatch(ligne))
00746         {
00747                 m_FaceType= coordinateAndTextureAndNormal;
00748         }
00749         else if (coordinateTextureRegExp.exactMatch(ligne))
00750         {
00751                 m_FaceType= coordinateAndTexture;
00752         }
00753         else if (coordinateNormalRegExp.exactMatch(ligne))
00754         {
00755                 m_FaceType= coordinateAndNormal;
00756         }
00757         else if (coordinateOnlyRegExp.exactMatch(ligne))
00758         {
00759                 m_FaceType= coordinate;
00760         }
00761         else
00762         {
00763                 QString message= "GLC_ObjToWorld::setObjType OBJ file not reconize";
00764                 message.append("\nAt line : ");
00765                 message.append(QString::number(m_CurrentLineNumber));
00766                 qDebug() << message;
00767                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00768                 clear();
00769                 throw(fileFormatException);
00770         }
00771 }
00772 
00773 // compute face normal
00774 GLC_Vector3df GLC_ObjToWorld::computeNormal(GLuint index1, GLuint index2, GLuint index3)
00775 {
00776         double xn, yn, zn;
00777 
00778         // Vertex 1
00779         xn= m_pCurrentObjMesh->m_Positions.at(index1 * 3);
00780         yn= m_pCurrentObjMesh->m_Positions.at(index1 * 3 + 1);
00781         zn= m_pCurrentObjMesh->m_Positions.at(index1 * 3 + 2);
00782         const GLC_Vector3d vect1(xn, yn, zn);
00783 
00784         // Vertex 2
00785         xn= m_pCurrentObjMesh->m_Positions.at(index2 * 3);
00786         yn= m_pCurrentObjMesh->m_Positions.at(index2 * 3 + 1);
00787         zn= m_pCurrentObjMesh->m_Positions.at(index2 * 3 + 2);
00788         const GLC_Vector3d vect2(xn, yn, zn);
00789 
00790         // Vertex 3
00791         xn= m_pCurrentObjMesh->m_Positions.at(index3 * 3);
00792         yn= m_pCurrentObjMesh->m_Positions.at(index3 * 3 + 1);
00793         zn= m_pCurrentObjMesh->m_Positions.at(index3 * 3 + 2);
00794         const GLC_Vector3d vect3(xn, yn, zn);
00795 
00796         const GLC_Vector3d edge1(vect3 - vect2);
00797         const GLC_Vector3d edge2(vect1 - vect2);
00798 
00799         GLC_Vector3d normal(edge1 ^ edge2);
00800         normal.normalize();
00801 
00802         return normal.toVector3df();
00803 }
00804 
00805 // clear objToWorld allocate memmory
00806 void GLC_ObjToWorld::clear()
00807 {
00808         m_CurrentMeshMaterials.clear();
00809         m_ListOfAttachedFileName.clear();
00810 
00811         if (NULL != m_pMtlLoader)
00812         {
00813                 delete m_pMtlLoader;
00814                 m_pMtlLoader= NULL;
00815         }
00816         if (NULL != m_pCurrentObjMesh)
00817         {
00818                 delete m_pCurrentObjMesh;
00819                 m_pCurrentObjMesh= NULL;
00820         }
00821 
00822 }
00823 // Merge Mutli line in one
00824 void GLC_ObjToWorld::mergeLines(QString* pLineBuff, QTextStream* p0bjStream)
00825 {
00826         if (pLineBuff->endsWith(QChar('\\')))
00827         {
00828                 pLineBuff->replace(QChar('\\'), QChar(' '));
00829                 pLineBuff->append(p0bjStream->readLine());
00830                 ++m_CurrentLineNumber;
00831                 mergeLines(pLineBuff, p0bjStream);
00832         }
00833 }
00834 
00835 // Add the current Obj mesh to the world
00836 void GLC_ObjToWorld::addCurrentObjMeshToWorld()
00837 {
00838         if (NULL != m_pCurrentObjMesh)
00839         {
00840                 if (!m_pCurrentObjMesh->m_Positions.isEmpty())
00841                 {
00842                         m_pCurrentObjMesh->m_pMesh->addVertice(m_pCurrentObjMesh->m_Positions.toVector());
00843                         m_pCurrentObjMesh->m_Positions.clear();
00844                         m_pCurrentObjMesh->m_pMesh->addNormals(m_pCurrentObjMesh->m_Normals.toVector());
00845                         m_pCurrentObjMesh->m_Normals.clear();
00846                         if (!m_pCurrentObjMesh->m_Texels.isEmpty())
00847                         {
00848                                 m_pCurrentObjMesh->m_pMesh->addTexels(m_pCurrentObjMesh->m_Texels.toVector());
00849                                 m_pCurrentObjMesh->m_Texels.clear();
00850                         }
00851                         QHash<QString, MatOffsetSize*>::iterator iMat= m_pCurrentObjMesh->m_Materials.begin();
00852                         while (m_pCurrentObjMesh->m_Materials.constEnd() != iMat)
00853                         {
00854                                 GLC_Material* pCurrentMaterial= NULL;
00855                                 if ((NULL != m_pMtlLoader) && (m_pMtlLoader->contains(iMat.key())))
00856                                 {
00857                                         pCurrentMaterial= m_pMtlLoader->material(iMat.key());
00858                                 }
00859                                 // Create the list of triangles to add to the mesh
00860                                 const int offset= iMat.value()->m_Offset;
00861                                 int size= iMat.value()->m_size;
00862                                 if (0 == size)
00863                                 {
00864                                         size= m_pCurrentObjMesh->m_Index.size() - offset;
00865                                 }
00866                                 //qDebug() << "Offset : " << offset << " size : " << size;
00867                                 QList<GLuint> triangles;
00868                                 for (int i= offset; i < (offset + size); ++i)
00869                                 {
00870                                         triangles.append(m_pCurrentObjMesh->m_Index.at(i));
00871                                 }
00872                                 // Add the list of triangle to the mesh
00873                                 if (!triangles.isEmpty())
00874                                 {
00875                                         m_pCurrentObjMesh->m_pMesh->addTriangles(pCurrentMaterial, triangles);
00876                                 }
00877 
00878                                 ++iMat;
00879                         }
00880                         if (m_pCurrentObjMesh->m_pMesh->faceCount() > 0)
00881                         {
00882                                 m_pCurrentObjMesh->m_pMesh->finish();
00883                                 GLC_3DRep* pRep= new GLC_3DRep(m_pCurrentObjMesh->m_pMesh);
00884                                 m_pWorld->rootOccurence()->addChild((new GLC_StructInstance(pRep)));
00885                         }
00886                         else
00887                         {
00888                                 delete m_pCurrentObjMesh->m_pMesh;
00889                         }
00890 
00891                 }
00892                 else
00893                 {
00894                         delete m_pCurrentObjMesh->m_pMesh;
00895                 }
00896 
00897                 delete m_pCurrentObjMesh;
00898                 m_pCurrentObjMesh= NULL;
00899         }
00900 }
00901 
00902 

SourceForge.net Logo

©2005 Laurent Ribon