glc_offtoworld.cpp

Go to the documentation of this file.
00001 
00002 /****************************************************************************
00003 
00004  This file is part of the GLC-lib library.
00005  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
00006  http://glc-lib.sourceforge.net
00007 
00008  GLC-lib is free software; you can redistribute it and/or modify
00009  it under the terms of the GNU Lesser General Public License as published by
00010  the Free Software Foundation; either version 3 of the License, or
00011  (at your option) any later version.
00012 
00013  GLC-lib is distributed in the hope that it will be useful,
00014  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  GNU Lesser General Public License for more details.
00017 
00018  You should have received a copy of the GNU Lesser General Public License
00019  along with GLC-lib; if not, write to the Free Software
00020  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021 
00022 *****************************************************************************/
00023 
00025 
00026 #include "glc_offtoworld.h"
00027 #include "../sceneGraph/glc_world.h"
00028 #include "../glc_fileformatexception.h"
00029 #include "../sceneGraph/glc_structreference.h"
00030 #include "../sceneGraph/glc_structinstance.h"
00031 #include "../sceneGraph/glc_structoccurence.h"
00032 
00033 #include <QTextStream>
00034 #include <QFileInfo>
00035 #include <QGLContext>
00036 
00037 GLC_OffToWorld::GLC_OffToWorld()
00038 : m_pWorld(NULL)
00039 , m_FileName()
00040 , m_CurrentLineNumber(0)
00041 , m_pCurrentMesh(NULL)
00042 , m_CurVertexIndex(0)
00043 , m_NbrOfVertexs(0)
00044 , m_NbrOfFaces(0)
00045 , m_IsCoff(false)
00046 , m_Is4off(false)
00047 , m_PositionBulk()
00048 , m_NormalBulk()
00049 , m_ColorBulk()
00050 , m_IndexList()
00051 {
00052 
00053 }
00054 
00055 GLC_OffToWorld::~GLC_OffToWorld()
00056 {
00057         clear();
00058 }
00059 
00061 // Set Functions
00063 
00064 // Create an GLC_World from an input OFF File
00065 GLC_World* GLC_OffToWorld::CreateWorldFromOff(QFile &file)
00066 {
00067         clear();
00068         m_FileName= file.fileName();
00070         // Test if the file exist and can be opened
00072         if (!file.open(QIODevice::ReadOnly))
00073         {
00074                 QString message(QString("GLC_OffToWorld::CreateWorldFromOff File ") + m_FileName + QString(" doesn't exist"));
00075                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotFound);
00076                 throw(fileFormatException);
00077         }
00078 
00080         // Init member
00082         m_pWorld= new GLC_World;
00083 
00084         // Create Working variables
00085         int currentQuantumValue= 0;
00086         int previousQuantumValue= 0;
00087 
00088         // Create the input file stream
00089         QTextStream offStream(&file);
00090 
00091         // QString buffer
00092         QString lineBuff;
00093 
00095         // Check the OFF Header
00097         // Check if the file begin with "OFF" or "COFF"
00098         ++m_CurrentLineNumber;
00099         lineBuff= offStream.readLine();
00100         lineBuff= lineBuff.trimmed();
00101         if(offStream.atEnd() || (!lineBuff.startsWith("OFF") && !lineBuff.startsWith("COFF") && !lineBuff.startsWith("4OFF")))
00102         {
00103                 QString message= "GLC_OffToWorld::CreateWorldFromOff : OFF or COFF header not found";
00104                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00105                 clear();
00106                 throw(fileFormatException);
00107         }
00108 
00109         // Set the COFF flag
00110         m_IsCoff= lineBuff.startsWith("COFF");
00111 
00112         // Set the 4OFF flag
00113         m_Is4off= lineBuff.startsWith("4OFF");
00114 
00115         // Create the mesh
00116         m_pCurrentMesh= new GLC_Mesh();
00117 
00118         // Set mesh color per vertex if needed
00119         if (m_IsCoff)
00120         {
00121                 m_pCurrentMesh->setColorPearVertex(true);
00122         }
00123         // Get the number of vertex and faces and skip comments
00124         ++m_CurrentLineNumber;
00125         lineBuff= offStream.readLine();
00126         lineBuff= lineBuff.trimmed();
00127         while(!offStream.atEnd() && lineBuff.startsWith(QChar('#')))
00128         {
00129                 ++m_CurrentLineNumber;
00130                 lineBuff= offStream.readLine();
00131                 lineBuff= lineBuff.trimmed();
00132         }
00133         extractNbrVertexsAndNbrFaces(lineBuff);
00134 
00136         // Read Buffer and load vertexs
00138         emit currentQuantum(currentQuantumValue);
00139 
00140         for (int currentVertex= 0; currentVertex < m_NbrOfVertexs; ++currentVertex)
00141         {
00142                 // Check it the end of file has been reached
00143                 if(offStream.atEnd())
00144                 {
00145                         QString message= "GLC_OffToWorld::CreateWorldFromOff : This file seems to be incomplete";
00146                         message.append("\nAt ligne : ");
00147                         message.append(QString::number(m_CurrentLineNumber));
00148                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00149                         clear();
00150                         throw(fileFormatException);
00151                 }
00152 
00153                 ++m_CurrentLineNumber;
00154                 lineBuff= offStream.readLine();
00155                 // Skip empty line
00156                 while (lineBuff.isEmpty())
00157                 {
00158                         ++m_CurrentLineNumber;
00159                         lineBuff= offStream.readLine();
00160                 }
00161                 // Add current vertex and color if needed to the mesh
00162                 extractVertex(lineBuff);
00163 
00164                 // Update Current Quantum for progress bar usage.
00165                 currentQuantumValue = static_cast<int>((static_cast<double>(currentVertex) / (m_NbrOfVertexs + m_NbrOfFaces)) * 100);
00166                 if (currentQuantumValue > previousQuantumValue)
00167                 {
00168                         emit currentQuantum(currentQuantumValue);
00169                 }
00170                 previousQuantumValue= currentQuantumValue;
00171         }
00172 
00174         // Read Buffer and load faces
00176         for (int currentFace= 0; currentFace < m_NbrOfFaces; ++currentFace)
00177         {
00178                 // Check it the end of file has been reached
00179                 if(offStream.atEnd())
00180                 {
00181                         QString message= "GLC_OffToWorld::CreateWorldFromOff : This file seems to be incomplete";
00182                         message.append("\nAt ligne : ");
00183                         message.append(QString::number(m_CurrentLineNumber));
00184                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotSupported);
00185                         clear();
00186                         throw(fileFormatException);
00187                 }
00188 
00189                 ++m_CurrentLineNumber;
00190                 lineBuff= offStream.readLine();
00191                 while (lineBuff.isEmpty())
00192                 {
00193                         ++m_CurrentLineNumber;
00194                         lineBuff= offStream.readLine();
00195                 }
00196 
00197                 // Add current Face to the mesh
00198                 extractFaceIndex(lineBuff);
00199 
00200                 // Update Current Quantum for progress bar usage.
00201                 currentQuantumValue = static_cast<int>((static_cast<double>(currentFace + m_NbrOfVertexs + 1) / (m_NbrOfVertexs + m_NbrOfFaces)) * 100);
00202                 if (currentQuantumValue > previousQuantumValue)
00203                 {
00204                         emit currentQuantum(currentQuantumValue);
00205                 }
00206                 previousQuantumValue= currentQuantumValue;
00207 
00208         }
00209 
00210         file.close();
00211         // Compute mesh normals
00212         computeNormal();
00213 
00214         m_pCurrentMesh->addVertice(m_PositionBulk.toVector());
00215         m_pCurrentMesh->addNormals(m_NormalBulk.toVector());
00216         if (!m_ColorBulk.isEmpty())
00217         {
00218                 m_pCurrentMesh->addColors(m_ColorBulk.toVector());
00219         }
00220         m_pCurrentMesh->addTriangles(NULL, m_IndexList);
00221 
00222         m_pCurrentMesh->finish();
00223         GLC_3DRep* pRep= new GLC_3DRep(m_pCurrentMesh);
00224         m_pCurrentMesh= NULL;
00225         m_pWorld->rootOccurence()->addChild(new GLC_StructOccurence(pRep));
00226 
00227         return m_pWorld;
00228 }
00229 
00231 // Private services Functions
00233 
00234 // clear offToWorld allocate memmory and reset member
00235 void GLC_OffToWorld::clear()
00236 {
00237         if (NULL != m_pCurrentMesh)
00238         {
00239                 delete m_pCurrentMesh;
00240                 m_pCurrentMesh= NULL;
00241         }
00242         m_pWorld= NULL;
00243         m_FileName.clear();
00244         m_CurrentLineNumber= 0;
00245         m_pCurrentMesh= NULL;
00246         m_CurVertexIndex= 0;
00247         m_NbrOfVertexs= 0;
00248         m_NbrOfFaces= 0;
00249         m_IsCoff= false;
00250         m_Is4off= false;
00251         m_PositionBulk.clear();
00252         m_NormalBulk.clear();
00253         m_ColorBulk.clear();
00254 }
00255 
00256 // Extract a Vertex from a string and add color component if needed
00257 void GLC_OffToWorld::extractVertex(QString &line)
00258 {
00259 
00260         QTextStream stringVecteur(&line);
00261 
00262         QString xString, yString, zString;
00263 
00264         if (((stringVecteur >> xString >> yString >> zString).status() == QTextStream::Ok))
00265         {
00266                 bool xOk, yOk, zOk;
00267                 m_PositionBulk.append(xString.toFloat(&xOk));
00268                 m_PositionBulk.append(yString.toFloat(&yOk));
00269                 m_PositionBulk.append(zString.toFloat(&zOk));
00270                 if (!(xOk && yOk && zOk))
00271                 {
00272                         QString message= "GLC_OffToWorld::extractVertex : failed to convert vertex component to float";
00273                         message.append("\nAt ligne : ");
00274                         message.append(QString::number(m_CurrentLineNumber));
00275                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00276                         clear();
00277                         throw(fileFormatException);
00278                 }
00279                 if (m_Is4off)
00280                 {
00281                         QString wString;
00282                         if (((stringVecteur >> wString).status() == QTextStream::Ok))
00283                         {
00284                                 float w;
00285                                 bool wOk;
00286                                 w= wString.toFloat(&wOk);
00287                                 if (!wOk)
00288                                 {
00289                                         QString message= "GLC_OffToWorld::extractVertex : failed to convert vertex fourth component to float";
00290                                         message.append("\nAt ligne : ");
00291                                         message.append(QString::number(m_CurrentLineNumber));
00292                                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00293                                         clear();
00294                                         throw(fileFormatException);
00295                                 }
00296                                 const int lastValue= m_PositionBulk.size() - 1;
00297                                 m_PositionBulk[lastValue - 2]= m_PositionBulk.at(lastValue - 2) / w;
00298                                 m_PositionBulk[lastValue - 1]= m_PositionBulk.at(lastValue - 1) / w;
00299                                 m_PositionBulk[lastValue]= m_PositionBulk.at(lastValue) / w;
00300                         }
00301                         else
00302                         {
00303                                 QString message= "GLC_OffToWorld::extractVertex : failed to read vector fourth component";
00304                                 message.append("\nAt ligne : ");
00305                                 message.append(QString::number(m_CurrentLineNumber));
00306                                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00307                                 clear();
00308                                 throw(fileFormatException);
00309                         }
00310                 }
00311 
00312                 // Test if the file is a COFF
00313                 if (m_IsCoff)
00314                 {
00315                         QString rString, gString, bString, aString;
00316 
00317                         if (((stringVecteur >> rString >> gString >> bString >> aString).status() == QTextStream::Ok))
00318                         {
00319                                 bool rOk, gOk, bOk, aOk;
00320                                 m_ColorBulk.append(rString.toFloat(&rOk));
00321                                 m_ColorBulk.append(gString.toFloat(&gOk));
00322                                 m_ColorBulk.append(bString.toFloat(&bOk));
00323                                 m_ColorBulk.append(aString.toFloat(&aOk));
00324                                 if (!(rOk && gOk && bOk && aOk))
00325                                 {
00326                                         QString message= "GLC_OffToWorld::extractVertex : failed to convert color component to float";
00327                                         message.append("\nAt ligne : ");
00328                                         message.append(QString::number(m_CurrentLineNumber));
00329                                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00330                                         clear();
00331                                         throw(fileFormatException);
00332                                 }
00333                         }
00334                         else
00335                         {
00336                                 QString message= "GLC_OffToWorld::extractVertex : failed to read vertex color";
00337                                 message.append("\nAt ligne : ");
00338                                 message.append(QString::number(m_CurrentLineNumber));
00339                                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00340                                 clear();
00341                                 throw(fileFormatException);
00342                         }
00343                 }
00344 
00345         }
00346         else
00347         {
00348                 QString message= "GLC_OffToWorld::extractVertex : failed to read vector component";
00349                 message.append("\nAt ligne : ");
00350                 message.append(QString::number(m_CurrentLineNumber));
00351                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00352                 clear();
00353                 throw(fileFormatException);
00354         }
00355 
00356 }
00357 
00358 // Extract Number off Vertex and faces
00359 void GLC_OffToWorld::extractNbrVertexsAndNbrFaces(QString &line)
00360 {
00361         QTextStream stringVecteur(&line);
00362 
00363         QString xString, yString;
00364 
00365         if (((stringVecteur >> xString >> yString).status() == QTextStream::Ok))
00366         {
00367                 bool xOk, yOk;
00368                 m_NbrOfVertexs= xString.toInt(&xOk);
00369                 m_NbrOfFaces= yString.toInt(&yOk);
00370                 if (!(xOk && yOk))
00371                 {
00372                         QString message= "GLC_OffToWorld::extractNbrVertexsAndNbrFaces : failed to convert text to int";
00373                         message.append("\nAt ligne : ");
00374                         message.append(QString::number(m_CurrentLineNumber));
00375                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00376                         clear();
00377                         throw(fileFormatException);
00378                 }
00379         }
00380         else
00381         {
00382                 QString message= "GLC_OffToWorld::extractNbrVertexsAndNbrFaces : failed to extract nbr of vertexs/faces";
00383                 message.append("\nAt ligne : ");
00384                 message.append(QString::number(m_CurrentLineNumber));
00385                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00386                 clear();
00387                 throw(fileFormatException);
00388 
00389         }
00390 }
00391 
00392 // Extract a face from a string
00393 void GLC_OffToWorld::extractFaceIndex(QString &line)
00394 {
00395         QString buff;
00396 
00397         QList<GLuint> indexList;
00398 
00400         // Parse the line containing face index
00402         QTextStream streamFace(&line);
00403         // Get the number of vertex
00404         if((streamFace >> buff).status() != QTextStream::Ok)
00405         {
00406                 QString message= "GLC_OffToWorld::extractFaceIndex failed to extract number of vertex index";
00407                 message.append("\nAt line : ");
00408                 message.append(QString::number(m_CurrentLineNumber));
00409                 message.append(QString("\n") + line);
00410                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00411                 clear();
00412                 throw(fileFormatException);
00413         }
00414         bool conversionOk;
00415         // Convert the QString Number of vertex to int
00416         int numberOfVertex= buff.toInt(&conversionOk);
00417         if (!conversionOk)
00418         {
00419                 QString message= "GLC_OffToWorld::extractFaceIndex failed to convert String to int";
00420                 message.append("\nAt line : ");
00421                 message.append(QString::number(m_CurrentLineNumber));
00422                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00423                 clear();
00424                 throw(fileFormatException);
00425         }
00426         // Extract the face's vertexs index
00427         for (int i= 0; i < numberOfVertex; ++i)
00428         {
00429                 // Get a vertex index
00430                 if((streamFace >> buff).status() != QTextStream::Ok)
00431                 {
00432                         QString message= "GLC_OffToWorld::extractFaceIndex failed to extract vertex index";
00433                         message.append("\nAt line : ");
00434                         message.append(QString::number(m_CurrentLineNumber));
00435                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00436                         clear();
00437                         throw(fileFormatException);
00438                 }
00439                 // Convert the QString vertex index into int
00440                 int index= buff.toInt(&conversionOk);
00441                 if (conversionOk)
00442                 {
00443                         indexList.append(index);
00444                 }
00445                 else
00446                 {
00447                         QString message= "GLC_ObjToWorld::extractFaceIndex failed to convert String to int";
00448                         message.append("\nAt line : ");
00449                         message.append(QString::number(m_CurrentLineNumber));
00450                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00451                         clear();
00452                         throw(fileFormatException);
00453                 }
00454         }
00455 
00456         // Trying to read face color
00457         QString rString, gString, bString;
00458         if((streamFace >> rString >> gString >> bString).status() == QTextStream::Ok)
00459         {
00460                 // Fill color bulk data if needed
00461                 if (m_ColorBulk.isEmpty())
00462                 {
00463                         const int size= m_PositionBulk.size() / 3 * 4;
00464                         for (int i= 0; i < size; ++i)
00465                         {
00466                                 m_PositionBulk.append(0.0);
00467                         }
00468                 }
00469                 float r, g, b;
00470                 bool rOk, gOk, bOk;
00471                 r= rString.toFloat(&rOk);
00472                 g= gString.toFloat(&gOk);
00473                 b= bString.toFloat(&bOk);
00474                 if (!rOk || !gOk || !bOk)
00475                 {
00476                         QString message= "GLC_ObjToWorld::extractFaceIndex failed to convert String to float";
00477                         message.append("\nAt line : ");
00478                         message.append(QString::number(m_CurrentLineNumber));
00479                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00480                         clear();
00481                         throw(fileFormatException);
00482                 }
00483                 for (int i= 0; i < numberOfVertex; ++i)
00484                 {
00485                         m_ColorBulk[indexList[i] * 4]= r;
00486                         m_ColorBulk[indexList[i] * 4 + 1]= g;
00487                         m_ColorBulk[indexList[i] * 4 + 2]= b;
00488                         m_ColorBulk[indexList[i] * 4 + 3]= 1.0f;
00489                 }
00490         }
00491 
00492         // Add the face to index List
00493         m_IndexList.append(indexList);
00494 }
00495 
00496 // compute face normal
00497 void GLC_OffToWorld::computeNormal()
00498 {
00499         //qDebug() << "GLC_OffToWorld::computeNormal";
00500         //qDebug() << "Position size= " << m_PositionBulk.size();
00501         //qDebug() << "Normal size= " << m_NormalBulk.size();
00502         const QList<float>* pData= &m_PositionBulk;
00503         // Fill the list of normal
00504         QList<float>* pNormal= &m_NormalBulk;
00505         const int normalCount= pData->size();
00506         for (int i= 0; i < normalCount; ++i)
00507         {
00508                 pNormal->append(0.0f);
00509         }
00510         // Compute the normals and add them to the current mesh info
00511         const int size= m_IndexList.size();
00512         double xn, yn, zn;
00513 
00514 
00515         for (int i= 0; i < size; i+=3)
00516         {
00517                 // Vertex 1
00518                 xn= pData->at(m_IndexList.at(i) * 3);
00519                 yn= pData->at(m_IndexList.at(i) * 3 + 1);
00520                 zn= pData->at(m_IndexList.at(i) * 3 + 2);
00521                 const GLC_Vector3d vect1(xn, yn, zn);
00522 
00523                 // Vertex 2
00524                 xn= pData->at(m_IndexList.at(i + 1) * 3);
00525                 yn= pData->at(m_IndexList.at(i + 1) * 3  + 1);
00526                 zn= pData->at(m_IndexList.at(i + 1) * 3 + 2);
00527                 const GLC_Vector3d vect2(xn, yn, zn);
00528 
00529                 // Vertex 3
00530                 xn= pData->at(m_IndexList.at(i + 2) * 3);
00531                 yn= pData->at(m_IndexList.at(i + 2) * 3 + 1);
00532                 zn= pData->at(m_IndexList.at(i + 2) * 3 + 2);
00533                 const GLC_Vector3d vect3(xn, yn, zn);
00534 
00535                 const GLC_Vector3d edge1(vect3 - vect2);
00536                 const GLC_Vector3d edge2(vect1 - vect2);
00537 
00538                 GLC_Vector3d normal(edge1 ^ edge2);
00539                 normal.normalize();
00540 
00541                 GLC_Vector3df curNormal= normal.toVector3df();
00542                 for (int curVertex= 0; curVertex < 3; ++curVertex)
00543                 {
00544                         (*pNormal)[m_IndexList.at(i + curVertex) * 3]= curNormal.x();
00545                         (*pNormal)[m_IndexList.at(i + curVertex) * 3 + 1]= curNormal.y();
00546                         (*pNormal)[m_IndexList.at(i + curVertex) * 3 + 2]= curNormal.z();
00547                 }
00548         }
00549 
00550 }
00551 

SourceForge.net Logo

©2005-2011 Laurent Ribon